I am working on a side-scrolling platformer and I just added scrolling, which broke my collision detection. I have no idea WHY collision detection no longer works, so I thought I’d see if anyone here can help me. I know the scrolling is causing the problem because every time I deactivate it, detection works fine.
WHAT IS HAPPENING
I am loading in a tile based level (10h x 16w in this case) and the level is surrounded by walls, including “walls” on the ground as the floor. The player appears on the left side on top of the floor and as I move him to the right, everything is fine. Once the player hits the middle of the screen, scrolling begins. The next wall tile (on the floor) that the player walks over causes him to fall through: no more collision detection.
THE CODE
Here’s the enter frame code:
protected function update(e:Event):void
{
_deltaTime = (getTimer() - _previousTime) / 1000;
_previousTime = getTimer();
readKeyInput();
applyForces();
movePlayer();
checkPlayerCollisions();
render();
updateCamera();
}
protected function readKeyInput():void
{
var movement:Vector3D = _config.playerMovement.clone();
movement.scaleBy(_deltaTime);
if (_keyLeftPressed)
{
_player.netForce.decrementBy(movement);
}
if (_keyRightPressed)
{
_player.netForce.incrementBy(movement);
}
}
protected function playerJump():void
{
if (_player.isJumping || _player.isFalling) return;
_player.isJumping = true;
var jump:Vector3D = _config.playerJump.clone();
_player.netForce.incrementBy(jump);
}
protected function applyForces():void
{
var gravity:Vector3D = _config.gravity.clone();
gravity.scaleBy(_deltaTime);
_player.netForce.incrementBy(gravity);
if (_player.isJumping)
{
_player.netForce.x *= _config.drag;
} else {
_player.netForce.x *= _config.friction;
}
}
protected function movePlayer():void
{
_player.tempX = _player.x + _player.netForce.x;
_player.tempY = _player.y + _player.netForce.y;
}
protected function checkPlayerCollisions():void
{
var testReference:GridReference = getCollisionReference(_player);
//CHECK INDIVIDUAL SPRITES
checkWalls(testReference);
}
** protected function checkWalls(testReference:GridReference):void
{
var testRect:Rectangle = _player.hitArea.getRect(this);
var oldRect:Rectangle = testRect.clone();
trace("Player X: ", _player.x, "Camera X: ", _camera.x);
testRect.x += _player.tempX - _player.x;
testRect.y += _player.tempY - _player.y;
var tempWallCount:int = 1;
var tempWallTrace:String = "";
for each(var wall:IWall in testReference._walls)
{
var wallRect:Rectangle = wall.getRect(this);
var intersection:Rectangle = wallRect.intersection(testRect);
tempWallTrace += "Wall " + tempWallCount + ": ";
tempWallCount++;
if (!intersection.width || !intersection.height) continue;
tempWallTrace += "Int Pass, ";
if (wallRect.top >= oldRect.bottom) //WALL IS BELOW
{
testRect.y -= intersection.height; //OFFSET BY INTERSECTION HEIGHT
_player.netForce.y = 0;
tempWallTrace += "Wall Below, ";
}
intersection = wallRect.intersection(testRect);
if (wallRect.right <= oldRect.left) //WALL IS TO THE LEFT
{
testRect.x += intersection.width;
if (intersection.width) _player.netForce.x = 0;
tempWallTrace += "Wall Left, ";
}
intersection = wallRect.intersection(testRect);
if (wallRect.left >= oldRect.right) //WALL IS TO THE RIGHT
{
testRect.x -= intersection.width;
if (intersection.width) _player.netForce.x = 0;
tempWallTrace += "Wall Right, ";
}
intersection = wallRect.intersection(testRect);
if (wallRect.bottom <= oldRect.top) //WALL IS ABOVE
{
testRect.y += intersection.height; //OFFSET BY INTERSECTION HEIGHT
if (intersection.height) _player.netForce.y = 0;
tempWallTrace += "Wall Up, ";
}
//ADJUST VALUES TO MATCH NEW RECT
_player.tempX = _player.x +(testRect.x - oldRect.x);
_player.tempY = _player.y +(testRect.y - oldRect.y);
tempWallTrace += "NewY - " + _player.tempY + " || ";
}
trace(tempWallTrace);
}**
protected function render():void
{
if (!_gameRunning) return;
_player.x = _player.tempX;
_player.y = _player.tempY;
}
protected function updateCamera():void
{
if (!_gameRunning) return;
_camera.x = (_player.x >= (_camera.width / 2)) ? _player.x - (_camera.width / 2) : 0;
_camera.x = Math.min(_camera.x, _backgroundOriginalWidth - _camera.width); //Correct for right side end
_background.scrollRect = _camera;
}
//END GAME LOOP LOGIC *********************************************************
protected function getCollisionReference(sprite:ISprite):GridReference
{
var testPoint:Point = getGridPosition(sprite);
var testReference:GridReference = new GridReference();
//CHECK THE CURRENT GRID REFERENCE AND THE EIGHT SURROUNDING ONES
testReference.concat(_collisionGrid.getGridReference(testPoint.x - 1, testPoint.y - 1));
testReference.concat(_collisionGrid.getGridReference(testPoint.x, testPoint.y - 1));
testReference.concat(_collisionGrid.getGridReference(testPoint.x + 1, testPoint.y - 1));
testReference.concat(_collisionGrid.getGridReference(testPoint.x - 1, testPoint.y));
testReference.concat(_collisionGrid.getGridReference(testPoint.x, testPoint.y));
testReference.concat(_collisionGrid.getGridReference(testPoint.x + 1, testPoint.y));
testReference.concat(_collisionGrid.getGridReference(testPoint.x - 1, testPoint.y + 1));
testReference.concat(_collisionGrid.getGridReference(testPoint.x, testPoint.y + 1));
testReference.concat(_collisionGrid.getGridReference(testPoint.x + 1, testPoint.y + 1));
return testReference;
}
**WHAT I’VE TRIED
**I have tried three different types of scrolling and all of them have this same issue:
[LIST=1]
[]Loop through every asset and move them individually according to key stroke
[]Put every asset in a sprite and move the sprite according to key stroke
[*]#2 plus add scrollRect centered on the player (current solution)
[/LIST]
I am now focusing on the checkWalls() function as the source of the problem, but I can’t figure out what’s happening.
Any ideas are welcome!