protected bool moveBolder(Map _theMap, int _pixelX, int _pixelY) { // First find out where we want to push the block to int tileX = _theMap.getTileNumFromPixelX(_pixelX); int tileY = _theMap.getTileNumFromPixelY(_pixelY); int newTileX = tileX; int newTileY = tileY; int diffX = _pixelX - m_position.X; int diffY = _pixelY - m_position.Y; float angle = 20.0f * Angles.DEG_1; float rotationMod = m_rotation; while (rotationMod > Angles.DEG_45) { rotationMod -= Angles.DEG_90; } if (Math.Abs(rotationMod) < angle) { if (Math.Abs(diffX) > Math.Abs(diffY)) { newTileX = tileX + diffX / Math.Abs(diffX); } else { newTileY = tileY + diffY / Math.Abs(diffY); } } else { if (Math.Abs(diffX) > Math.Abs(diffY)) { if (Math.Abs(diffY) != 0) { newTileY = tileY + diffY / Math.Abs(diffY); } } else { if (Math.Abs(diffX) != 0) { newTileX = tileX + diffX / Math.Abs(diffX); } } } // Secondly now we need to check if the way if blocked TileType destination = _theMap.getMapTileType(newTileX, newTileY); if(destination == TileType.FLOOR) { if (!isAnyCharacterOnTile(_theMap, new Point2(newTileX, newTileY))) { _theMap.setMapTileType(tileX, tileY, TileType.FLOOR); _theMap.setMapTileType(newTileX, newTileY, TileType.USABLE_BOLDER); return true; } } return false; }
bool TestPositionAgainDiagonalWalls(Map _theMap, int minX, int minY, int maxX, int maxY, ref bool environmentCollision, ref Point2 newPos) { bool collidedOnDiagonal = false; Point2 result = new Point2(); Point2 slideBlockCentre = new Point2(); Point2 localNewPos = new Point2(newPos); bool localEnvironmentCollision = environmentCollision; for (int y = minY; y < maxY; y++) { for (int x = minX; x < maxX; x++) { if (x >= _theMap.getWidth() / _theMap.getTileWidth() && y >= _theMap.getHeight() / _theMap.getTileHeight()) { continue; } TileType tileType = _theMap.getMapTileType(x, y); Point2 pixel = new Point2( x * _theMap.getTileWidth(), y * _theMap.getTileHeight()); int pixelCenX = pixel.X + _theMap.getTileWidth() / 2; int pixelCenY = pixel.Y + _theMap.getTileHeight() / 2; m_boundingTileCircle.Center = new Vector3(pixelCenX, pixelCenY, 0); m_boundingTileCircle.Radius = _theMap.getTileWidth() / 2; if (Map.isTileTypeDiagonalWall(tileType) && _theMap.isTileTypePixelCollision(tileType)) { TileType pixelCheckType = _theMap.GetTileTypePixelCollision(tileType); Point2 topLeft = new Point2( localNewPos.X - m_tileSet.getTileWidth() / 2, localNewPos.Y - m_tileSet.getTileHeight() / 2); bool localIntersects = m_tileSet.checkForCollision(_theMap.getTileSet(), m_frameIndexCollision, topLeft, (int)pixelCheckType, pixel); if (localIntersects) { if (Map.isTileTypeDiagonalWall(tileType)) { if (localEnvironmentCollision || collidedOnDiagonal) { localNewPos = new Point2(m_position); } else { if (GetSlidePositionOffDiagonalBlock(tileType, m_position, localNewPos, ref result, pixel)) { localNewPos = new Point2(result); } else { slideBlockCentre = new Point2(pixelCenX, pixelCenY); GetSlidePositionOffBlock(m_position, localNewPos, slideBlockCentre, _theMap.getTileWidth(), m_characterRadius, ref localNewPos); } collidedOnDiagonal = true; } localEnvironmentCollision = true; } } } // if diagonal wall } // for loop } // for loop environmentCollision = localEnvironmentCollision; newPos.X = localNewPos.X; newPos.Y = localNewPos.Y; return collidedOnDiagonal; }
public bool movePosition(float frameTime, Map _theMap, Character[] _characterArray, bool slideAgainstWalls, bool canUseSlides) { bool movingOnSlide = false; bool slideAgainstDiagonalWalls = slideAgainstWalls && true; bool environmentCollision = false; // todo this shouldnt be assigned here each frame m_characterRadius = m_tileSet.getTileWidth() / 2 * 8 / 10; Point2 change = new Point2(); int tileIndexX = m_position.X / _theMap.getTileWidth(); int tileIndexY = m_position.Y / _theMap.getTileHeight(); TileType tileTypeStoodOn = _theMap.getMapTileType(tileIndexX, tileIndexY); Boolean onSlide = Map.isTileTypeSlide(tileTypeStoodOn) && canUseSlides; int SLIDE_EXIT_LENGTH = 10; // If not sliding (on slide exit) then allow movement if (!onSlide) { float moveSpeed = m_moveSpeedPerSecond * frameTime; float cos = (float)Math.Cos(m_rotation); float sin = (float)Math.Sin(m_rotation); change.X = (int)( sin * moveSpeed); change.Y = (int)(-cos * moveSpeed); } Point2 newPos = new Point2(); // Velocity is only for slide movement if (m_velocity.Length() > MAX_VELOCITY) { m_velocity.Normalize(); m_velocity *= MAX_VELOCITY; } change.X += (int)(m_velocity.X * frameTime); newPos.X = m_position.X + change.X; change.Y += (int)(m_velocity.Y * frameTime); newPos.Y = m_position.Y + change.Y; if (Map.isTileTypeSlide(tileTypeStoodOn) && canUseSlides) { Vector2 targetPoint = new Vector2(); Vector2 charPoint = new Vector2(m_position.X, m_position.Y); targetPoint.X = tileIndexX * _theMap.getTileWidth() + m_tileSet.getTileWidth() / 2; targetPoint.Y = tileIndexY * _theMap.getTileHeight() + m_tileSet.getTileHeight() / 2; if (tileTypeStoodOn == TileType.SLIDE_DOWN) { targetPoint.Y += m_tileSet.getTileHeight(); } else if (tileTypeStoodOn == TileType.SLIDE_UP) { targetPoint.Y -= m_tileSet.getTileHeight(); } else if (tileTypeStoodOn == TileType.SLIDE_LEFT) { targetPoint.X -= m_tileSet.getTileWidth(); } else if (tileTypeStoodOn == TileType.SLIDE_RIGHT) { targetPoint.X += m_tileSet.getTileWidth(); } Vector2 vector = targetPoint - charPoint; // Its important this is high to keep the player in the center of the slide // So they dont come out off-center and get stuck in collision const float VELOCITY_INCREASE = 200.0f; m_velocity += vector * VELOCITY_INCREASE * frameTime; movingOnSlide = true; } else if (m_velocity.Length() > 0) { // dubious code to reduce velocity m_velocity *= (25 * frameTime); change.X += (int)(m_velocity.X * frameTime); change.Y += (int)(m_velocity.Y * frameTime); newPos.X = m_position.X + change.X; newPos.Y = m_position.Y + change.Y; if (m_velocity.Length() < SLIDE_EXIT_LENGTH) { m_velocity.X = 0; m_velocity.Y = 0; stopMovement(); } } else { newPos.X = m_position.X + change.X; newPos.Y = m_position.Y + change.Y; } Point2 lastPos = new Point2(newPos); // check per tile here if (Map.isTileTypeSlide(tileTypeStoodOn) == false && BuildConstants.COLLISION_OFF == false)// && onSlide == false)// && m_teleporting == false) { // Check against the very boundarys of the map newPos.X = capValue(newPos.X, m_characterRadius, _theMap.getWidth() - m_characterRadius); newPos.Y = capValue(newPos.Y, m_characterRadius, _theMap.getHeight() - m_characterRadius); if (lastPos.X != newPos.X || lastPos.Y != newPos.Y) { environmentCollision = true; } int minX = capValue(tileIndexX - 1, 0, _theMap.getWidth() / _theMap.getTileWidth()); int maxX = capValue(tileIndexX + 2, 0, _theMap.getWidth() / _theMap.getTileWidth()); int minY = capValue(tileIndexY - 1, 0, _theMap.getHeight() / _theMap.getTileHeight()); int maxY = capValue(tileIndexY + 2, 0, _theMap.getHeight() / _theMap.getTileHeight()); m_boundingCharCircle.Center = new Vector3(newPos.X, newPos.Y, 0); m_boundingCharCircle.Radius = m_characterRadius; for (int y = minY; y < maxY; y++) { for (int x = minX; x < maxX; x++) { if (x >= _theMap.getWidth() / _theMap.getTileWidth() && y >= _theMap.getHeight() / _theMap.getTileHeight()) { continue; } TileType tileType = _theMap.getMapTileType(x, y); Point2 pixel = new Point2( x * _theMap.getTileWidth(), y * _theMap.getTileHeight()); bool intersects = false; int pixelCenX = pixel.X + _theMap.getTileWidth() / 2; int pixelCenY = pixel.Y + _theMap.getTileHeight() / 2; m_boundingTileCircle.Center = new Vector3(pixelCenX, pixelCenY, 0); m_boundingTileCircle.Radius = _theMap.getTileWidth() / 2; if (Map.isTileTypeSquareBlock(tileType, m_frameIndexRendering) || (canUseSlides == false && Map.isTileTypeSlide(tileType))) { m_boundingTileBox = BoundingBox.CreateFromSphere(m_boundingTileCircle); bool localIntersects = m_boundingCharCircle.Intersects(m_boundingTileBox); if(localIntersects) { if (slideAgainstWalls) { if (GetSlidePositionOffBlock(m_position, newPos, new Point2(pixelCenX, pixelCenY), _theMap.getTileWidth(), m_characterRadius, ref newPos)) { environmentCollision = true; } } else { intersects = true; } } } else if (Map.isTileTypeCircle(tileType)) { intersects = m_boundingCharCircle.Intersects(m_boundingTileCircle); } else if (_theMap.isTileTypePixelCollision(tileType)) { TileType pixelCheckType = _theMap.GetTileTypePixelCollision(tileType); Point2 topLeft = new Point2( newPos.X - m_tileSet.getTileWidth() / 2, newPos.Y - m_tileSet.getTileHeight() / 2); bool localIntersects = m_tileSet.checkForCollision(_theMap.getTileSet(), m_frameIndexCollision, topLeft, (int)pixelCheckType, pixel); if (localIntersects && (!Map.isTileTypeDiagonalWall(tileType) || slideAgainstDiagonalWalls == false)) { intersects = localIntersects; } } if (intersects) { environmentCollision = true; newPos = new Point2(m_position); } } } // 2nd pass for diagonal walls if (slideAgainstDiagonalWalls) { TestPositionAgainDiagonalWalls(_theMap, minX, minY, maxX, maxY, ref environmentCollision, ref newPos); } m_boundingCharCircle.Center = new Vector3(newPos.X, newPos.Y, 0); m_boundingCharCircle.Radius = m_characterRadius; if (_characterArray != null) { // Check against other characters for (int c = 0; c < _characterArray.Length; c++) { if (_characterArray[c] == this || _characterArray[c].m_health <= 0 || _characterArray[c].m_finishedLevel) { continue; } BoundingSphere otherCharBounding = new BoundingSphere(); otherCharBounding.Center = new Vector3(_characterArray[c].m_position.X, _characterArray[c].m_position.Y, 0); otherCharBounding.Radius = m_characterRadius; if (m_boundingCharCircle.Intersects(otherCharBounding)) { if (m_frameIndexRendering == (int)CharacterTile.BADDY) { _characterArray[c].applyDamageDrain(frameTime, GameConstants.baddyDrainAmountPerSec); continue; } // characters are facing each other // This means if characters do occupy the same space (via resurrection or teleport) then they can still move appart else if (IsFacing(_characterArray[c])) { newPos = new Point2(m_position); } } } } } if (slideAgainstWalls) { m_position.X = newPos.X; m_position.Y = newPos.Y; } else { int realChangeX = newPos.X - m_position.X; int percentageX = 100; // This will let user get stuck on things instead of just sliding around if (change.X * change.X > realChangeX * realChangeX) { percentageX = 100 * realChangeX / change.X; } int realChangeY = newPos.Y - m_position.Y; int percentageY = 100; // This will let user get stuck on things instead of just sliding around if (change.Y * change.Y > realChangeY * realChangeY) { percentageY = 100 * realChangeY / change.Y; } int lowestPercentage = percentageX < percentageY ? percentageX : percentageY; // Calculate final position m_position.X += change.X * lowestPercentage / 100; m_position.Y += change.Y * lowestPercentage / 100; } SetMovingOnSlideState(movingOnSlide); return environmentCollision; }