Reputation: 125
So this question is a little more abstract than some. Say I have a game that I only want to render once per second, such as a Tetris clone. I only want to process one input per second, then render the new frame accordingly. Tetris is a grid-based game, so I can't just move the game piece by a certain amount times the timeDelta
float that people usually use for frame rate examples. How do I go about only rendering one frame per second in a grid-based game? Here's what code I have so far, but it's wrong:
void Engine::Go(){
while(window.isOpen()){
if(timeElapsed >= 1000){
timeElapsed = clock.restart().asMilliseconds();;
ProcessInput();
}
UpdateCPU();
Render();
timeElapsed = clock.getElapsedTime().asMilliseconds();
time += timeElapsed;
}
}
void Engine::ProcessInput(){
while(window.pollEvent(event)){
if(event.type == (sf::Event::Closed))
window.close();
}
//process movement detection of piece
int temp = level.GetGamePieces().size();
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left)){
level.GetGamePieces().at(temp - 1).GetPieceSprite().move(-10, 0);
std::cout << "left";
moved = true;
}
else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right)){
level.GetGamePieces().at(temp - 1).GetPieceSprite().move(10,0);
std::cout << "right";
moved = true;
}
else{
level.GetGamePieces().at(temp - 1).GetPieceSprite().move(0,10);
std::cout << "down";
moved = true;
}
}
I only want to move the gamepiece one sqaure at a time, once per second, but I just don't know how to do this.
Edit: Here's the code that renders the frames
void Engine::Render(){
window.clear();
//draw wall tiles
for(int i = 0; i < 160; i++){
if(i < 60){
level.GetWallTile().setPosition(0, i * 10);
window.draw(level.GetWallTile());
}
if(i >= 60 && i < 100){
level.GetWallTile().setPosition((i - 60) * 10, 590);
window.draw(level.GetWallTile());
}
if(i >= 100){
level.GetWallTile().setPosition(390, (i - 100) * 10);
window.draw(level.GetWallTile());
}
}
//draw BG tiles
for(int i = 1; i < 39; i++){
for(int j = 0; j < 59; j++){
level.GetBGTile().setPosition(i * 10, j * 10);
window.draw(level.GetBGTile());
}
}
for(int i = 0; i < level.GetGamePieces().size(); i++){
window.draw(level.GetGamePieces()[i].GetPieceSprite());
}
window.display();
}
Upvotes: 0
Views: 596
Reputation: 1499
You are not accounting for the fact that a user may want to move a shape in between movements of the shape.
You should allow the user to move the shape left, right, and down whenever he/she wants to, but not force the downward movement until after the elapsed time has completed.
When I made a block-based game, here's what I did
void updateSeconds( double deltaTime ) {
// If timer until shape falls runs out, move the shape down.
timeUntilShapeDrop -= deltaTime;
if ( timeUntilShapeDrop > 0 || currentFallingShape->isAnimating() ) {
return;
}
// If ( shape collides with map when moved down )
currentFallingShape->move(-1,0);
if ( currentFallingShape->isCollisionWithMap ( * map ) ) {
currentFallingShape->move(1,0);
// Lock shape in place on the map
currentFallingShape->setBlocksOnMap( * map );
lastUpdateLinesCleared = clearFullLines();
}
timeUntilShapeDrop = calculateShapeDropTimeInterval();
I also included gradual shape animation if you're interested one way of how to do it. I built a graphical game map on top of the logical map and used the logical map to start the graphical interpolation. I broke the graphics library I was using, but the logic code is still good for reference or use if you'd like.
Upvotes: 1