void GD_API MoveObjects( RuntimeScene & scene ) { RuntimeObjList allObjects = scene.objectsInstances.GetAllObjects(); for (unsigned int id = 0;id < allObjects.size();++id) { allObjects[id]->SetX( allObjects[id]->GetX() + allObjects[id]->TotalForceX() * static_cast<double>(scene.GetElapsedTime())/1000000.0 ); allObjects[id]->SetY( allObjects[id]->GetY() + allObjects[id]->TotalForceY() * static_cast<double>(scene.GetElapsedTime())/1000000.0 ); allObjects[id]->UpdateForce( static_cast<double>(scene.GetElapsedTime())/1000000.0 ); } return; }
/** * Called at each frame before events : * Position the object on the path */ void PathBehavior::DoStepPreEvents(RuntimeScene & scene) { if(!isPathLoaded) { LoadPath(scene); Reset(); } // add to the current time along the path timeOnSegment += static_cast<double>(scene.GetElapsedTime())/1000000.0*speed; // if I reached the end of this segment, move to a new segment if (timeOnSegment >= totalSegmentTime && currentSegment < path.size()) EnterSegment(currentSegment + 1); //Position object on the segment sf::Vector2f newPos; if ( !path.empty() && currentSegment < path.size()-1 ) newPos = offset + path[currentSegment] + (path[currentSegment + 1] - path[currentSegment]) * (timeOnSegment / totalSegmentTime); else { if ( stopAtEnd && !path.empty()) newPos = path.back() + offset; else if (reverseAtEnd) { std::reverse(path.begin(), path.end()); EnterSegment(0); if (!path.empty()) newPos = path.front() + offset; } else { EnterSegment(0); if (!path.empty()) newPos = path.front() + offset; } } object->SetX(newPos.x); object->SetY(newPos.y); return; }
void PlatformerObjectAutomatism::DoStepPreEvents(RuntimeScene & scene) { if ( parentScene != &scene ) //Parent scene has changed { parentScene = &scene; sceneManager = parentScene ? &ScenePlatformObjectsManager::managers[&scene] : NULL; floorPlatform = NULL; } if ( !sceneManager ) return; double timeDelta = static_cast<double>(scene.GetElapsedTime())/1000000.0; //0.1) Get the player input: double requestedDeltaX = 0; double requestedDeltaY = 0; //Change the speed according to the player's input. leftKey |= !ignoreDefaultControls && sf::Keyboard::isKeyPressed( sf::Keyboard::Left ); rightKey |= !ignoreDefaultControls && sf::Keyboard::isKeyPressed( sf::Keyboard::Right ); if ( leftKey ) currentSpeed -= acceleration*timeDelta; if ( rightKey ) currentSpeed += acceleration*timeDelta; //Take deceleration into account only if no key is pressed. if ( leftKey == rightKey ) { bool wasPositive = currentSpeed>0; currentSpeed -= deceleration*timeDelta*(wasPositive ? 1.0 : -1.0); //Set the speed to 0 if the speed was top low. if ( wasPositive && currentSpeed < 0 ) currentSpeed = 0; if ( !wasPositive && currentSpeed > 0 ) currentSpeed = 0; } if (currentSpeed > maxSpeed) currentSpeed = maxSpeed; if (currentSpeed < -maxSpeed) currentSpeed = -maxSpeed; requestedDeltaX += currentSpeed*timeDelta; //Compute the list of the objects that will be used std::set<PlatformAutomatism*> potentialObjects = GetPotentialCollidingObjects(std::max(requestedDeltaX, maxFallingSpeed)); std::set<PlatformAutomatism*> overlappedJumpThru = GetJumpthruCollidingWith(potentialObjects); //Check that the floor object still exists and is near the object. if ( isOnFloor && potentialObjects.find(floorPlatform) == potentialObjects.end() ) { isOnFloor = false; floorPlatform = NULL; } //0.2) Track changes in object size //Stick the object to the floor if its height has changed. if ( trackSize && isOnFloor && oldHeight != object->GetHeight() && !scene.IsFirstLoop() ) object->SetY(object->GetY()+oldHeight-object->GetHeight()); oldHeight = object->GetHeight(); //1) X axis: //Shift the object according to the floor movement. if ( isOnFloor ) { requestedDeltaX += floorPlatform->GetObject()->GetX() - floorLastX; requestedDeltaY += floorPlatform->GetObject()->GetY() - floorLastY; } //Move the object on x axis. double oldX = object->GetX(); if ( requestedDeltaX != 0 ) { object->SetX(object->GetX()+requestedDeltaX); //Colliding: Try to push out from the solid. //Note that jump thru are never obstacle on X axis. while ( IsCollidingWith(potentialObjects, floorPlatform, /*excludeJumpthrus=*/true) ) { if ( (requestedDeltaX > 0 && object->GetX() <= oldX) || (requestedDeltaX < 0 && object->GetX() >= oldX) ) { object->SetX(oldX); //Unable to move the object without being stuck in an obstacle. break; } //If on floor: try get up a bit to bypass not perfectly aligned floors. if ( isOnFloor ) { object->SetY(object->GetY()-1); if ( !IsCollidingWith(potentialObjects, floorPlatform, /*excludeJumpthrus=*/true) ) break; object->SetY(object->GetY()+1); } object->SetX(floor(object->GetX())+(requestedDeltaX > 0 ? -1 : 1)); currentSpeed = 0; //Collided with a wall } } //2) Y axis: //Go on a ladder ladderKey |= !ignoreDefaultControls && sf::Keyboard::isKeyPressed(sf::Keyboard::Up); if (ladderKey && IsOverlappingLadder(potentialObjects)) { canJump = true; isOnFloor = false; floorPlatform = NULL; currentJumpSpeed = 0; currentFallSpeed = 0; isOnLadder = true; } if ( isOnLadder ) { upKey |= !ignoreDefaultControls && sf::Keyboard::isKeyPressed(sf::Keyboard::Up); downKey |= !ignoreDefaultControls && sf::Keyboard::isKeyPressed(sf::Keyboard::Down); if ( upKey ) requestedDeltaY -= 150*timeDelta; if ( downKey ) requestedDeltaY += 150*timeDelta; //Coming to an extremity of a ladder if ( !IsOverlappingLadder(potentialObjects) ) { isOnLadder = false; } } //Fall if (!isOnFloor && !isOnLadder) { currentFallSpeed += gravity*timeDelta; if ( currentFallSpeed > maxFallingSpeed ) currentFallSpeed = maxFallingSpeed; requestedDeltaY += currentFallSpeed*timeDelta; requestedDeltaY = std::min(requestedDeltaY, maxFallingSpeed*timeDelta); } //Jumping jumpKey |= !ignoreDefaultControls && (sf::Keyboard::isKeyPressed( sf::Keyboard::LShift ) || sf::Keyboard::isKeyPressed( sf::Keyboard::RShift ) ); if ( canJump && jumpKey ) { jumping = true; canJump = false; //isOnFloor = false; If floor is a very steep slope, the object could go into it. isOnLadder = false; currentJumpSpeed = jumpSpeed; currentFallSpeed = 0; //object->SetY(object->GetY()-1); } if ( jumping ) { requestedDeltaY -= currentJumpSpeed*timeDelta; currentJumpSpeed -= gravity*timeDelta; if ( currentJumpSpeed < 0 ) { currentJumpSpeed = 0; jumping = false; } } //Follow the floor if ( isOnFloor ) { if ( object->IsCollidingWith(floorPlatform->GetObject()) ) { //Floor is getting up, as the object is colliding with it. double oldY = object->GetY(); int step = 0; bool stillInFloor = false; do { if ( step >= floor(abs(requestedDeltaX*slopeClimbingFactor)) ) //Slope is too step ( > max angle ) { object->SetY(object->GetY()-(abs(requestedDeltaX*slopeClimbingFactor)-(double)step)); //Try to add the decimal part. if ( object->IsCollidingWith(floorPlatform->GetObject()) ) stillInFloor = true; //Too steep. break; } //Try to get out of the floor. object->SetY(object->GetY()-1); step++; } while ( object->IsCollidingWith(floorPlatform->GetObject() ) ); if ( stillInFloor ) { object->SetY(oldY); //Unable to follow the floor ( too steep ): Go back to the original position. object->SetX(oldX); //And also revert the shift on X axis. } } else { //Floor is flat or get down. double oldY = object->GetY(); object->SetY(object->GetY()+1); int step = 0; bool noMoreOnFloor = false; while ( !IsCollidingWith(potentialObjects) ) { if ( step > abs(requestedDeltaX*slopeClimbingFactor) ) //Slope is too step ( > 50% ) { noMoreOnFloor = true; break; } //Object was on floor, but no more: Maybe a slope, try to follow it. object->SetY(object->GetY()+1); step++; } if ( noMoreOnFloor ) object->SetY(oldY); //Unable to follow the floor: Go back to the original position. Fall will be triggered next tick. else object->SetY(object->GetY()-1); //Floor touched: Go back 1 pixel over. } } //Move the object on Y axis if ( requestedDeltaY != 0 ) { double oldY = object->GetY(); object->SetY(object->GetY()+requestedDeltaY); //Stop when colliding with an obstacle. while ( (requestedDeltaY < 0 && IsCollidingWith(potentialObjects, NULL, /*excludeJumpThrus=*/true)) //Jumpthru = obstacle <=> Never when going up || (requestedDeltaY > 0 && IsCollidingWith(potentialObjects, overlappedJumpThru)) ) //Jumpthru = obstacle <=> Only if not already overlapped when goign down { jumping = false; currentJumpSpeed = 0; if ( (requestedDeltaY > 0 && object->GetY() <= oldY) || (requestedDeltaY < 0 && object->GetY() >= oldY) ) { object->SetY(oldY); //Unable to move the object without being stuck in an obstacle. break; } object->SetY(floor(object->GetY())+(requestedDeltaY > 0 ? -1 : 1)); } } //3) Update the current floor data for the next tick: overlappedJumpThru = GetJumpthruCollidingWith(potentialObjects); if ( !isOnLadder ) { //Check if the object is on a floor: //In priority, check if the last floor platform is still the floor. double oldY = object->GetY(); object->SetY(object->GetY()+1); if ( isOnFloor && object->IsCollidingWith(floorPlatform->GetObject() ) ) { //Still on the same floor floorLastX = floorPlatform->GetObject()->GetX(); floorLastY = floorPlatform->GetObject()->GetY(); } else { //Check if landing on a new floor: (Exclude already overlapped jump truh) std::set<PlatformAutomatism*> collidingObjects = GetPlatformsCollidingWith(potentialObjects, overlappedJumpThru); if ( !collidingObjects.empty() ) //Just landed on floor { isOnFloor = true; canJump = true; jumping = false; currentJumpSpeed = 0; floorPlatform = *collidingObjects.begin(); floorLastX = floorPlatform->GetObject()->GetX(); floorLastY = floorPlatform->GetObject()->GetY(); currentFallSpeed = 0; } else //In the air { canJump = false; isOnFloor = false; floorPlatform = NULL; } } object->SetY(oldY); } //4) Do not forget to reset pressed keys leftKey = false; rightKey = false; ladderKey = false; upKey = false; downKey = false; jumpKey = false; //5) Track the movement hasReallyMoved = abs(object->GetX()-oldX) >= 1; }