I'm going over my main game loop and just cleaning it up some. Does this look right? <Spawn Delay (ARE)> <Piece Falls> <Lock Delay> <Clear Lines> <if any lines were cleared, a line clear delay> <collapse the graph> <loop> I'm not talking about one particular implementation, just a general loop. So if there's something in one of the popular implementations that's missing, I want to add it in. (You can always 0 it's delay and it's like it's not there).
Lock delay is a little more complicated than that, but you're close. This is the way I see it: Code: DO Spawn piece, applying entry delay Update next piece display DO WHILE piece is active Process input IF piece is on ground Handle lockdown rules ELSE Reset lockdown timer is appropriate ENDIF LOOP Add the final position of the falling piece to the field Check for "shapes" to be handled DO WHILE unprocessed shapes still exist Process each shape, removing it from the field if necessary Apply line clear delay Apply gravity Check for new shapes that have since been created LOOP LOOP UNTIL game end condition is met
Of course, if your language doesn't have coroutines, you're probably going to need to implement those LOOPs as a state machine. Think of Magic: The Gathering with its untap, upkeep, etc. Falling block style puzzle games would need at least the following states: entry, falling, landed, search for patterns, and gravity.
Nice! That's exactly what I was doing. I had a set of disparate booleans that arose as need and only sort-of-kind-of described the state of the game-engine. Not to mention the main timeStep loop was best described as a mess. Everything worked just fine, but the approach was seriously flawed. I moved to a single unified gameState variable. Currently it has these game states, but I may have to create some more. I'm uncertain. SPAWNING, FALLING, LOCKING, COLLAPSING. (Along with PAUSED and GAME_OVER) I chose these four for a specific reason. Excluding FALLING, each of the other three has a delay associated with it, Spawning has Are, Locking has LockDelay, and Collapsing has clearDelay. Each of these states says "I'm waiting to Lock, and then I'm going to Lock." Each state also has a function associated with it. For example lockingTimeStep() looks like this: Code: public void lockingTimeStep() { lockDelayTimer -= level.frameRate; processRotations(); processDrops(); processShifts(); processHolds(); if(canAddPiece(currentBlock,blockOrient,blockX,blockY+1)) { gameState = FALLING; } else if( lockDelayTimer <= 0 ) { addPiece( currentBlock, blockOrient, blockX, blockY ); score += level.scoreValues[0]; boolean linesCleared = clearLines(); if( linesCleared ) { collapseDelayTimer = level.collapseDelay; gameState = COLLAPSING; } else { spawnDelayTimer = level.spawnDelay; gameState = SPAWNING; } } } I considered creating seperate states for LOCK, CLEAR and SPAWN, but in the end I it doesn't seem worthwhile. They would exist for only a frame and they don't really need to be seperate as far as I can see. They work well as part of the current framework. I haven't yet added any pattern-searching. It's trivial to add to this system and I will eventually, but I still have bigger fish to fry.