public void BindEntityToTiles(GameEntity entity, bool bind) { for (int i = getTileIndexFromLeftEdgeX(entity.getLeftEdgeX()); i <= getTileIndexFromRightEdgeX(entity.getRightEdgeX()); i++) { for (int j = getTileIndexFromTopEdgeY(entity.getTopEdgeY()); j <= getTileIndexFromBottomEdgeY(entity.getBottomEdgeY()); j++) { Tile currTile = currLevel.getTile(i, j); if (currTile != null) //if within bounds of level { currLevel.getTile(i, j).BindEntity(entity, bind); } } } }
public void moveGameEntity(GameEntity entity, int dx, int dy) { BindEntityToTiles(entity, false); if (!entity.isCollidable()) //skip collision detection { moveGameEntityWithoutCollision(entity, entity.x + dx, entity.y + dy); BindEntityToTiles(entity, true); return; } bool wallCollision = false; //calculate number of tiles distance covers int tilesX = (int)Math.Floor((float)Math.Abs(dx) / Static.TILE_WIDTH) + 1; int tilesY = (int)Math.Floor((float)Math.Abs(dy) / Static.TILE_HEIGHT) + 1; //get entity bounds int leftEdgeTile = getTileIndexFromLeftEdgeX(entity.getLeftEdgeX()); int rightEdgeTile = getTileIndexFromRightEdgeX(entity.getRightEdgeX()); int topEdgeTile = getTileIndexFromTopEdgeY(entity.getTopEdgeY()); int bottomEdgeTile = getTileIndexFromBottomEdgeY(entity.getBottomEdgeY()); int distanceToTravelX = dx; int distanceToTravelY = dy; //find distance to level boundary in movement direction and see if it is less move amount //figure out how many tiles your movement translates to in each direction //scan tiles in front of you to find closest obstacle in that direction //final movement is min of original movement and distance to obstacle if (dx > 0) { //right int distanceToBoundary = currLevel.GetTilesHorizontal() * Static.TILE_WIDTH - entity.getRightEdgeX(); if (distanceToBoundary < distanceToTravelX) { distanceToTravelX = distanceToBoundary; //wallCollision = true; } int tilesToScanX = tilesX; if (rightEdgeTile + tilesToScanX > currLevel.GetTilesHorizontal() - 1) { tilesToScanX = currLevel.GetTilesHorizontal() - 1 - rightEdgeTile; } for (int i = 1; i <= tilesToScanX; i++) { for (int j = topEdgeTile; j <= bottomEdgeTile; j++) { Tile currTile = currLevel.getTile(rightEdgeTile + i, j); if (currTile.isObstacle()) { int distanceToTile = currTile.x - entity.getRightEdgeX(); if (distanceToTile < distanceToTravelX) { distanceToTravelX = distanceToTile; wallCollision = true; break; } } GameEntity closest = null; foreach (GameEntity tileEntity in currTile.getEntities()) { if (tileEntity.getLeftEdgeX() - entity.getRightEdgeX() < distanceToTravelX) { if (tileEntity.OverlapsY(entity)) { distanceToTravelX = tileEntity.getLeftEdgeX() - entity.getRightEdgeX(); closest = tileEntity; } } } if (closest != null) { collisions.Add(new Collision(entity, closest)); } } } } else if (dx < 0) { //left int distanceToBoundary = -1 * entity.getLeftEdgeX(); if (distanceToBoundary > distanceToTravelX) { distanceToTravelX = distanceToBoundary; //wallCollision = true; } int tilesToScanX = tilesX; if (leftEdgeTile - tilesToScanX < 0) { tilesToScanX = leftEdgeTile; } for (int i = 1; i <= tilesToScanX; i++) { for (int j = topEdgeTile; j <= bottomEdgeTile; j++) { Tile currTile = currLevel.getTile(leftEdgeTile - i, j); if (currTile.isObstacle()) { int distanceToTile = (currTile.x + Static.TILE_WIDTH) - entity.getLeftEdgeX(); if (distanceToTile > distanceToTravelX) { distanceToTravelX = distanceToTile; wallCollision = true; break; } } GameEntity closest = null; foreach (GameEntity tileEntity in currTile.getEntities()) { if (tileEntity.getRightEdgeX() - entity.getLeftEdgeX() > distanceToTravelX) { if (tileEntity.OverlapsY(entity)) { distanceToTravelX = tileEntity.getRightEdgeX() - entity.getLeftEdgeX(); closest = tileEntity; } } } if (closest != null) { collisions.Add(new Collision(entity, closest)); } } } } entity.x = entity.x + distanceToTravelX; entity.hitbox.Offset(distanceToTravelX, 0); leftEdgeTile = getTileIndexFromLeftEdgeX(entity.getLeftEdgeX()); rightEdgeTile = getTileIndexFromRightEdgeX(entity.getRightEdgeX()); if (dy > 0) { //down int distanceToBoundary = currLevel.GetTilesVertical() * Static.TILE_HEIGHT - entity.getBottomEdgeY(); if (distanceToBoundary < distanceToTravelY) { distanceToTravelY = distanceToBoundary; //wallCollision = true; } int tilesToScanY = tilesY; if (bottomEdgeTile + tilesToScanY > currLevel.GetTilesVertical() - 1) { tilesToScanY = currLevel.GetTilesVertical() - 1 - bottomEdgeTile; } for (int i = 1; i <= tilesToScanY; i++) { for (int j = leftEdgeTile; j <= rightEdgeTile; j++) { Tile currTile = currLevel.getTile(j, bottomEdgeTile + i); if (currTile.isObstacle()) { int distanceToTile = currTile.y - entity.getBottomEdgeY(); if (distanceToTile < distanceToTravelY) { distanceToTravelY = distanceToTile; wallCollision = true; break; } } GameEntity closest = null; foreach (GameEntity tileEntity in currTile.getEntities()) { if (tileEntity.getTopEdgeY() - entity.getBottomEdgeY() < distanceToTravelY) { if (tileEntity.OverlapsX(entity)) { distanceToTravelY = tileEntity.getTopEdgeY() - entity.getBottomEdgeY(); closest = tileEntity; } } } if (closest != null) { collisions.Add(new Collision(entity, closest)); } } } } else if (dy < 0) { //up int distanceToBoundary = -1 * entity.getTopEdgeY(); if (distanceToBoundary > distanceToTravelY) { distanceToTravelY = distanceToBoundary; //wallCollision = true; } int tilesToScanY = tilesY; if (topEdgeTile - tilesToScanY < 0) { tilesToScanY = topEdgeTile; } for (int i = 1; i <= tilesToScanY; i++) { for (int j = leftEdgeTile; j <= rightEdgeTile; j++) { Tile currTile = currLevel.getTile(j, topEdgeTile - i); if (currTile.isObstacle()) { int distanceToTile = (currTile.y + Static.TILE_HEIGHT) - entity.getTopEdgeY(); if (distanceToTile > distanceToTravelY) { distanceToTravelY = distanceToTile; wallCollision = true; break; } } GameEntity closest = null; foreach (GameEntity tileEntity in currTile.getEntities()) { if (tileEntity.getBottomEdgeY() - entity.getTopEdgeY() > distanceToTravelY) { if (tileEntity.OverlapsX(entity)) { distanceToTravelY = tileEntity.getBottomEdgeY() - entity.getTopEdgeY(); closest = tileEntity; } } } if (closest != null) { collisions.Add(new Collision(entity, closest)); } } } } entity.y = entity.y + distanceToTravelY; entity.hitbox.Offset(0, distanceToTravelY); if (wallCollision) { entity.collideWithWall(); } BindEntityToTiles(entity, true); }
public bool OverlapsX(GameEntity entity) { return ((this.getRightEdgeX() > entity.getLeftEdgeX() && this.getRightEdgeX() < entity.getRightEdgeX()) || (this.getLeftEdgeX() < entity.getRightEdgeX() && this.getLeftEdgeX() > entity.getLeftEdgeX()) || (this.getLeftEdgeX() >= entity.getLeftEdgeX() && this.getRightEdgeX() <= entity.getRightEdgeX()) || (this.getLeftEdgeX() <= entity.getLeftEdgeX() && this.getRightEdgeX() >= entity.getRightEdgeX())); }