Hello! New to Lua and new to game development, but having a blast so far! Pardon a newbie's questions.
Long story short, I'm trying to implement my own version of this: https://www.youtube.com/watch?v=X9UAIaZ30wg&t=30s
It's a straightforward puzzle game, so I figured I could get by just looking up how to do things as I go, but for the Love of me I can't find answers to some basic questions.
I'm wondering what some accepted approaches are to the following dilemmas:
1) The game has some frame-precise maneuvers to execute that I'd like to preserve. So far, I've created a framerate controller by incrementing a global variable "gametime" with dt every update call, and calling "advanceframe" everytime "gametime/fps" is a new number. If a button is pressed and "input" is nil, then "input = key", and "input" is reset every frame. So basically I ignore all but the first input per frame. Is this okay? Would this cause any noticeable lag with the keyboard inputs at 30fps? Are there better framerate models I could learn from?
2) I need to check for rows/columns of matching color, and find clusters. Not all clusters are equal though, due to chains. As I have the program set up right now, there is a grid with rows (to make it easier to add and remove rows, as the height of the grid is not fixed), and each row has a tile, which can either have its content be nothing, a block, or garbage. What's the best way to look for matches? Just brute-force for loops? As it stands, I don't know a good way to check columns.
3) I need things to happen at a certain time. For instance, .5 seconds after a match is found, the blocks must disappear in sequence. What's the best way to accomplish this? Would some sort of callback timer based on elapsed frames be a good approach?
Thanks for any advice at all!
Grid Puzzle Game
Forum rules
Before you make a thread asking for help, read this.
Before you make a thread asking for help, read this.
Re: Grid Puzzle Game
What kind of frame-precise maneauvers are you talking about? I didn't really see anything in the video that wouldn't work just as well based on time elapsed as it would based on a fixed framerate. Maybe if we understand why it needs frame-precision we can help with it. (It's something a lot of people seem to ask for, but few games actually need)
As for #2, I'd say the best starting point for chain-finding would be the block(s) that have changed. There seem to be 3 ways that I saw in which chains can change; there's swapping two blocks (which would need a new chain-find to start for both of the blocks swapped), there's a block falling down (which would need a new chain-find for the falling block) and there's a new block appearing (which would need a chain-find for the new block)
It might be a good idea to write the chain-finder in a seperate thread and have it pass found chains back to the main thread, that way the graphics will remain smooth even if it's churning through a lot of code to find chains.
And for #3, use a callback timer based on elapsed time, not frames passed. You can just count dt itself to measure precisely how much time has passed. Other than that, using a callback is a good idea.
As for #2, I'd say the best starting point for chain-finding would be the block(s) that have changed. There seem to be 3 ways that I saw in which chains can change; there's swapping two blocks (which would need a new chain-find to start for both of the blocks swapped), there's a block falling down (which would need a new chain-find for the falling block) and there's a new block appearing (which would need a chain-find for the new block)
It might be a good idea to write the chain-finder in a seperate thread and have it pass found chains back to the main thread, that way the graphics will remain smooth even if it's churning through a lot of code to find chains.
And for #3, use a callback timer based on elapsed time, not frames passed. You can just count dt itself to measure precisely how much time has passed. Other than that, using a callback is a good idea.
Re: Grid Puzzle Game
I guess I'm being a bit greedy with the frames. I want to preserve more than just the look&feel of the game, but the mechanisms as well. In the game, there are a couple of what are most likely unintentional ways to get chains. For instance, http://puu.sh/aUJsH/52749741c8.png, http://puu.sh/aZY9X/f05774414e.png. Here's the list these are from (there are a ton): https://web.archive.org/web/20120326181 ... is_attack/.
Whereas many of these were probably "mistakes" in the original code, the community has largely adopted these as acceptable techniques, and many experts have mastered the timing needed for some of these, notably inputting the command within the exact 1/30s window given. Though now that I've talked through it, I realize I can create just that, an appropriate 1/30s window.... Would there be any problems with throttling input still, to allow only 1 input every .033333 seconds? Since the sprite-animations will all be based on 30fps, would it make sense to limit the input accordingly, or are there better options?
Ah, that makes sense. So should a "changed" block call some sort of signal on its neighbors to alert them to "look" for a matching row/column? Is there a better OOP model here than having a Grid with Rows with Tiles? Should each tile just have a neighbor list of orthogonal tiles?
In the case that the chain-finder is a separate thread, what would happen if it doesn't find the chains fast enough? Would it be a sort of visual lag, where there's clearly one on the screen, but it takes an extra moment or two to clear it from the board?
Whereas many of these were probably "mistakes" in the original code, the community has largely adopted these as acceptable techniques, and many experts have mastered the timing needed for some of these, notably inputting the command within the exact 1/30s window given. Though now that I've talked through it, I realize I can create just that, an appropriate 1/30s window.... Would there be any problems with throttling input still, to allow only 1 input every .033333 seconds? Since the sprite-animations will all be based on 30fps, would it make sense to limit the input accordingly, or are there better options?
Ah, that makes sense. So should a "changed" block call some sort of signal on its neighbors to alert them to "look" for a matching row/column? Is there a better OOP model here than having a Grid with Rows with Tiles? Should each tile just have a neighbor list of orthogonal tiles?
In the case that the chain-finder is a separate thread, what would happen if it doesn't find the chains fast enough? Would it be a sort of visual lag, where there's clearly one on the screen, but it takes an extra moment or two to clear it from the board?
Re: Grid Puzzle Game
Okay, I understand better what you mean with frame-precise moves. Answers to your questions, not neccesarily in the original order:
Rather than limiting when a user can give input (which is strange) it's probably better to determine when input is appropriate. I'm not sure if you have any movement related code in the grid yet, but here's what I'd do:
When a block no longer has anything beneath it, move it down to the next grid slot immediately. However, also set a timer on the block. This is the fall-timer. When drawing the block in question, draw it a little higher on the screen based on how much falling time is left (assuming linear falling speed). When firing up the chain-searcher, ignore any blocks that still have a fall-timer active (so that you can't make matching with falling blocks). When accepting input, ignore any blocks with a fall-timer larger than whatever quick-switch window you want to give the user.
When a block's fall timer runs out; if there's still nothing beneath it, immediately make it start falling again. This should give the user a really short period of time just before the block passes below the horizontal line seperating grid tiles. If there is something beneath the block, call the chain-finder.
That should make it work pretty much as you describe, without hooking yourself onto really weird "bugs" in your own code. Hope it helps.
Yeah it would turn into visual lag. So, on second thought, you probably don't want a second thread, you just want to make sure your search algorithm is fast enough and run it in the main thread, since visual lag would be unacceptable anyway.In the case that the chain-finder is a separate thread, what would happen if it doesn't find the chains fast enough? Would it be a sort of visual lag, where there's clearly one on the screen, but it takes an extra moment or two to clear it from the board?
It would probably be easier to feed the whole grid and the modified block to a function, since it needs to keep a checklist of which blocks have already been checked (so you don't get stuck in a loop) and keep a tally of the length of a chain. Other than that, yeah you'd need to start with the changed block, check each neighbour, and then check those neighbours as well if it's part of the chain. Then depending on the length of the chain, either score points or not.Ah, that makes sense. So should a "changed" block call some sort of signal on its neighbors to alert them to "look" for a matching row/column? Is there a better OOP model here than having a Grid with Rows with Tiles? Should each tile just have a neighbor list of orthogonal tiles?
It's always complicated to reintroduce "features" that are really just bugs in the old system. So keep in mind you're making things a bit harder on yourself by doing this. That said; let's go at it.Whereas many of these were probably "mistakes" in the original code, the community has largely adopted these as acceptable techniques, and many experts have mastered the timing needed for some of these, notably inputting the command within the exact 1/30s window given.
Rather than limiting when a user can give input (which is strange) it's probably better to determine when input is appropriate. I'm not sure if you have any movement related code in the grid yet, but here's what I'd do:
When a block no longer has anything beneath it, move it down to the next grid slot immediately. However, also set a timer on the block. This is the fall-timer. When drawing the block in question, draw it a little higher on the screen based on how much falling time is left (assuming linear falling speed). When firing up the chain-searcher, ignore any blocks that still have a fall-timer active (so that you can't make matching with falling blocks). When accepting input, ignore any blocks with a fall-timer larger than whatever quick-switch window you want to give the user.
When a block's fall timer runs out; if there's still nothing beneath it, immediately make it start falling again. This should give the user a really short period of time just before the block passes below the horizontal line seperating grid tiles. If there is something beneath the block, call the chain-finder.
That should make it work pretty much as you describe, without hooking yourself onto really weird "bugs" in your own code. Hope it helps.
Who is online
Users browsing this forum: No registered users and 2 guests