Jump to content
IGNORED

A Two-Player Competitive and Co-Op "Tetris" for the Atari 2600 VCS


AkashicRecord

Recommended Posts

I need to start thinking about pseudo-random number generation at some point, so no better time than now. I can also use it in debugging and testing.

 

A random number (modulo 7) was my standard method for choosing the next game piece, but all computers can only generate pseudo-random numbers...the pattern of numbers will repeat after some time.

 

Obviously, an 8-bit number is out of the question. Using 16 bits will repeat the game piece sequence after ~65,000 pieces (for the crude RNGs)...which I think isn't terrible, but it isn't optimal. (In some of my older games I used the Mersenne Twister algorithm.)

An 8-bit LFSR should be sufficient if update Rand every frame, but only use the value based on player input.

 

http://www.randomterrain.com/atari-2600-lets-make-a-game-spiceware-10.html

  • Like 1
Link to comment
Share on other sites

An 8-bit LFSR should be sufficient if update Rand every frame, but only use the value based on player input. http://www.randomterrain.com/atari-2600-lets-make-a-game-spiceware-10.html

I like this idea.

 

I was thinking of initially seeding using the "random" data in uninitialized RAM on startup, but this might cause unintended behavior on some emulators (unless specifically checking for zeroes...then the program can kind of assume that it is running on an emulator and use a different initialization.)

Link to comment
Share on other sites

An 8-bit LFSR should be sufficient if update Rand every frame, but only use the value based on player input. http://www.randomterrain.com/atari-2600-lets-make-a-game-spiceware-10.html

I did plan on having some game modes where players can set the starting seed values for the PRNG so as to have some "fixed" games. Those would probably be the best modes 1for contests and high score comparisons, etc. to be more fair.

 

I think I'll have the RAM to burn for a 16-bit generator, so I'm not to worried about that.

Link to comment
Share on other sites

There is really no reason to go 2K over 4K, except for bragging rights. It has been said that one hasn't truly coded for the VCS until they have done a full game in 2K, since that was the original constraints of the system. But Eproms are cheaper now than they were in 1977...

Are new 5v EPROMs still manufactured, or are they all new old stock (write once) or recycled (eraseable)? Ditto for 5v ttl/cmos chips. There seem to be good supply on them on sites like mouser and digikey, but I'm curious if they're really new or nos. Seems only hobbiests buy these. Most modern devices use 3.3v flash storage in smt packages.
  • Like 1
Link to comment
Share on other sites

Thanks for all the great posts, keep it coming! :)


This morning, I modified the color cycling test on page 3 and added the generic 8-bit LFSR.

This is an example that quickly shows how pecking away a few times at the RNG exposes a repeating sequence (...I think...) as the piece gets "stuck" on a number before repeating. The background and the animation speed are "randomized" together, but are static sequences. Using player input would provide different and better sequences, obviously.. Messing around with silly stuff like this too much is almost seizure-inducing, so caveat emptor and all that shit. :P

random-test.bin

One possible idea I had was to keep part of the RNG in RAM and periodically modify the internals of the generator. I'll have to experiment with some sequences to see what works and what doesn't...

Edited by AkashicRecord
Link to comment
Share on other sites

....so, obviously I don't want my pseudo-random number generator to take up most of my game's CPU (...or ROM, ...or RAM), so using an allegedly "bad" LFSR generator in combination with chaotic inputs (like user joystick input) might be the best 50 / 50 approach.

Edited by AkashicRecord
Link to comment
Share on other sites

So now we investigate adding crude joystick input. This example is a modification of the previous .bin but adds support to read a few joystick directions.

 

This one (very quickly) randomizes the background with left and right inputs, and decrements / increments the color value more slowly for down and up inputs (because the least significant bit isn't used for color if odd).

 

js-random-test.bin

 

Nothing special, but it's another small step forward.

Edited by AkashicRecord
Link to comment
Share on other sites

Obviously we won't want the game pieces flying left and right across the screen at light speed, so I'll have to perform some input filtering and smoothing later.

 

I suppose the next steps will be finalizing the game playfield and translating to screen positions and then on to collision detection and scoring...

Link to comment
Share on other sites

This is probably one of the last seizure-inducing randomness test .bins. (Don't say I didn't warn you...) The following is a small modification of the previous, but the behavior here is different:

 

post-66218-0-54835500-1540266031.png

 

new-js-random-test.bin

 

- Joystick up and down events increase and decrease the background color value from its current value.

 

- Joystick left and right events sap from the RNG (quite rapidly) but only take effect and show a color change when the frame counter expires (every 47 frames or so.)

 

- The game piece falling downscreen is constantly taking the color value of the RNG on every frame...this should cycle every 255 reps or so, but this will happen so fast that it should be humanly impossible to really see any pattern.

 

 

This test seems to increase the randomness quite organically for almost no hit to memory or CPU at all...

Edited by AkashicRecord
  • Like 2
Link to comment
Share on other sites

I always knew that the Sega Genesis controllers worked with the 2600 but I don't want to require one to play this game. I would like to take advantage of the controller (if available) because that simplifies the issue I will have with clockwise and counterclockwise rotation. As for the standard joystick, I have a few things to nail down in regard to user input:. For my previous Tetris titles, playability and control was a major factor...probably the biggest, and it was the one thing that I spent the most time in adjusting. (I put many hundreds of hours of testing into that!)

 

With the standard joystick, I would need to use a combination of something like holding up UP and pressing the BUTTON for counterclockwise rotations, with the fire button being the default clockwise rotation. However, I still wanted to have at least one way to perform a fast piece drop, so that should obviously be achieved by holding DOWN on the stick, but I also wanted to have a piece swapping feature where you can save your current piece and exchange it out for another one that you had previously saved...so that will be an issue trying to cram these features into useful controller inputs without anything getting in the way of playability or making things complicated and unintuitive....

 

I suppose I can forgo the counterclockwise rotation when piece-swapping is enabled (maybe left difficulty A / B?) or, I could just make that be a simple UP on the joystick. Holding up and pressing the button could perform the piece swap in that case. I don't want to put people that DON'T have a Genesis controller at a disadvantage, though. It shouldn't be a required peripheral, or anything that gives you a huge advantage over the standard joystick...

 

 

Just thinking out loud over a cup of coffee...

Edited by AkashicRecord
Link to comment
Share on other sites

AkashicRecord,

 

Your game looks great, really like your ideas you have displayed using different shades of the same color for pieces, as well as for background graphics. It's such a beautiful effect on the machine.

Thanks, I always thought the machine had a great palette and was capable of some good graphics. I'm glad that I'm hitting my design mockups almost 100%.

 

I do have an issue with the playfield though, because its really only one color. I'm still thinking about what I can do to "fake" it a bit and create an illusion of color differences without too much flickering. This isn't a priority at this point, but it is an aesthetic that I'd like to aim for. As it stands, the pieces will lock in to the playfield and just be a solid color...it's a bit boring compared to the detail of the game pieces and the playfield gradient.

Edited by AkashicRecord
Link to comment
Share on other sites

Today I've started a little bit of work on horizontal positioning. I figured I'd get part of this out of the way before moving on to work on the playfield dynamics some more...that part is much easier. In addition to horizontal positioning, I need to look some more at the drawing strategies for the game pieces and playfield. There are a few situations that the graphics kernel for this game is going to encounter:

 

1.) having to draw player 1

2.) having to draw player 2

3.) having to draw player 1 *and* player 2

4.) having to draw player 1 and a playfield change

5.) having to draw player 2 and a playfield change

 

6.) having to draw player 1 and player 2 (and playfield changes)

7.) having to draw no players (but with playfield changes)

8.) having to draw nothing at all... (i.e.; the default empty line state with no players on the scanline either)

9.) something else.... Score? "Next piece" display? "Saved piece" display? "Ghost" drop location, etc...

 

 

It looks like a lot when you write it out, doesn't it?

 

It looks like there is almost a need for 8 or more different "mini" kernels. This can probably be driven by a simple bitmap which instructs the kernel as to which scenario is needing to be handled for the upcoming scanlines. Luckily, this is going to happen (pretty much) in blocks of 8 scanlines, so we will have some pre-setup time before reaching the target scanline(s) where any work needs to be done.

 

On one hand, I want to be sort of "generic" and be able to handle some of the drawing routines in a more programmatic fashion...like subroutines...rather than just hard-coding a bunch of specific edge cases. If that last line didn't make sense, it means that there are some pieces and rotations that just might be better to "cheat" on. For instance, there is no rotation for a square piece, so pressing a button to rotate it is kind of nonsensical...but it would seem very weird to the player if the square piece was the only piece that didn't make a "flip" sound if you try to flip it....so the only thing you really need to do for a square piece is trigger the "flipping" sound...

 

On the other hand, unless I *really* want to try to shoot for a 2K ROM, I'll have a bit of code to burn to just do things the easy way and to make sure that everything just works. I don't need to aimlessly JSR to a subroutine to flip a piece which can never be flipped (to use the previous example again. I can already see that the square piece should be piece #0 to facilitate a BNE/BEQ/BPL for the other 6 pieces...) For most game pieces, there are only a few key positions in the game grid that need to be checked to see if a move is possible. Eliminating wasteful code which only serves to be more reusable might be exactly what I want to do. CPU and RAM is what is at a premium here; I'm not trying to write a VCS Tetris in as few lines of code (or bytes) as possible...I just want it to work well and to work within the "standard" boundaries (2-4K), and to look sexy AF...

Edited by AkashicRecord
Link to comment
Share on other sites

Solving the "one button" issue:

 

Since having only one button constrains the player to having only one direction to rotate the game pieces, I thought that it might be helpful to do two things.

 

It might help to add some extra time at the beginning of a new piece, regardless of difficulty level. This way since the player may be forced to having to rotate a "J" or "L" block three times (instead of one counter-clockwise) to move into a playable position. If it is physically impossible for a player to place a piece, then the game is...unplayable.

 

Another idea was to also randomize the piece rotation as well, instead of having every piece start in a default orientation.

Edited by AkashicRecord
Link to comment
Share on other sites

So, my crude input handler started dropping scanlines (as I was kind of expecting) on some inputs after adding 2P detection with buttons.

 

I sort of expected this because BIT instructions are pretty slow (and I wasn't paying attention to page boundaries, and it's probably not exactly in the best place either.) This won't be hard to fix though. I figured I should get the worst of the input handler out of the way early.

 

One of the upcoming prototypes will have piece-flipping with buttons. It's starting to look more like Tetris. :)

 

 

My 3 year-old son got a hold of the joystick color test program earlier, and was fascinated with it. (His favorite Atari 2600 games are Hangman and Fun With Numbers...)

Link to comment
Share on other sites

I always knew that the Sega Genesis controllers worked with the 2600 but I don't want to require one to play this game. I would like to take advantage of the controller (if available) because that simplifies the issue I will have with clockwise and counterclockwise rotation. As for the standard joystick, I have a few things to nail down in regard to user input:. For my previous Tetris titles, playability and control was a major factor...probably the biggest, and it was the one thing that I spent the most time in adjusting. (I put many hundreds of hours of testing into that!)

 

With the standard joystick, I would need to use a combination of something like holding up UP and pressing the BUTTON for counterclockwise rotations, with the fire button being the default clockwise rotation. However, I still wanted to have at least one way to perform a fast piece drop, so that should obviously be achieved by holding DOWN on the stick, but I also wanted to have a piece swapping feature where you can save your current piece and exchange it out for another one that you had previously saved...so that will be an issue trying to cram these features into useful controller inputs without anything getting in the way of playability or making things complicated and unintuitive....

 

I suppose I can forgo the counterclockwise rotation when piece-swapping is enabled (maybe left difficulty A / B?) or, I could just make that be a simple UP on the joystick. Holding up and pressing the button could perform the piece swap in that case. I don't want to put people that DON'T have a Genesis controller at a disadvantage, though. It shouldn't be a required peripheral, or anything that gives you a huge advantage over the standard joystick...

 

 

Just thinking out loud over a cup of coffee...

Paddle inputs read backwards compared to joystick inputs. Proper detdction system for Genesis controllers or paddles is pin 5 is always high, but normally low for joysticks. A Genesis controller will also pull pin 9 high until the C button is pressed.

 

Tetris normally rotates blocks clockwise for single button control scheme. For two button controls, the right button is clockwise, left for counterclockwise. Good news is B on the Genesis is always Fire on the joystick, so you have your primary button. For detection purposes, If pin 5 = high and pin 9 = low, then "press c button". If pin 5 and 9 are both low, no action. If pin 5 and 9 are both high, no action.

 

Here's where it gets a little dicey. Normally with two button controls, the right button is cw and left is ccw. One button, cw only. But since Your primary fire is on the left and your secondary fire on the right (which most controlkers don't have), the button scheme will be ccw (backwards) for one button and standard for two buttons, or cw (standard) for one button, then your second button will be ccw for two button play (backwards).

 

So my proposal is to allow the user to swap spin direction (both buttons) using a difficulty switch to reverse layout. That way players can utiluze proper muscle memory for either one button or two buttin standard. My one gripe with Chetriy (albeit minor) is lack of auxiliary C button on the Genesis. Getting three cw ritations in before setting a peice whena ccw rotation would suffice, is a pita.

 

Lastly don't use up for hard drops. That was so annoying when the Tetris company started doing that. Sk many lameo games ruined because i accidentally placed a piece and couldn't recover.

  • Like 1
Link to comment
Share on other sites

Alright, now that will save me quite a bit of time and testing right there. I only had planned to use one difficulty switch to disable the "next" display and the swapping or hold feature, so the other could be used to modify the input scheme.

 

I can definitely forgo the "hard" drop and go with something closer to the Tengen Tetris (it had a soft drop which had an acceleration factor the longer you held DOWN.) That game had a very nice feel to it.

Edited by AkashicRecord
Link to comment
Share on other sites

As for rotating pieces, I always used a small delay before "autorotating"

 

There was a very fine line in timing for a button press-and-release event to take place (usually a couple frames on average.) If the delay or smoothing factor was not good, the rotations would be too fast or two slow, and the feature becomes useless...or just plain gets in the way. I used to check to see if the button was still down over a cojuple frames before flagging an "autorotate" sequence to start and continue while the button is held.

 

It may be useful for me to whip up a joystick test program to collect some real world input timings. The test program would go something like this: You press and release the joystick button (as fast as possible) and the screen will flash a solid color while it is held, and then displays a frame timer value that shows how many frames it took before you could release the button, and the screen goes black again. (I have an idea for another one which flashes the screen at a random frame to see if you can release the button in time...kind of like a reaction test.)

 

Collecting some input data like this from users on actual hardware could go a long way into tweaking game input for the best mechanics and feel, as well as for "priming" the game engine. For the most part, people have a fast button tap speed, and a more casual button press speed. Finding the balance between these is key, because having extra features like a piece swapping function sort of complicates the input and timing scheme as well...

 

In a nutshell, you want it to be faster to hold the button to complete 3 auto-rotations faster than if you just tapped the button 3 times quickly...otherwise there's no time saved and the feature is useless... At the same time, you don't want the autorotate to kick in too fast, and you don't want it to flip the pieces so fast that you can't judge when to let go of the button...the reaction test idea above might be good for basing the autorotate mechanics on.

 

This level of attention to detail is what separates an average game from an excellent one.

Edited by AkashicRecord
Link to comment
Share on other sites

This might be the last silly joystick color test, but I wanted to add button recognition (only 1 controller now) and also wanted to move some of the code around. I wasn't working under the umbrella of the VBLANK and OVERSCAN timers (as I thought.) This fixes that bad behavior and also run the Random routine at a slightly different spot.

 

JS-button-RAND.bin

 

So this one again just quickly randomizes the LFSR generator with left and right inputs changing the PF color every "tick" (which is 30 frames, or 1/2 second), and up and down inputs increment and decrement the gradient, but this time while holding the button, the color changes instantly with the left and right inputs. You'll kind of see how quickly you can pres and release the button this way since the color will flash every frame while the button is held in conjunction with left / right stick input... (That sounded more confusing than it is.)

 

 

I should probably flip back over the the specifics of the graphics drawing routines for the game pieces now. I need to minimize what is actually done on each scanline as much as possible. I'm still leaning towards my "blackout" drawing method which just changes the sprite color a few times. The "black" sprites should be positioned within VBLANK and only "turned on" for specific scanlines via a color change. Hitting two color changes (one for each player) and playfield updates seem within close reach now...

Edited by AkashicRecord
Link to comment
Share on other sites

I'm reposting the T-block mockup image since I'm going to start with this one, since it is one of the more complicated pieces, and also because it has four orientations like the "J" and "L" blocks.

 

post-66218-0-74108800-1540490707.png

 

Converting to code, I stumbled upon a slightly different way to shade the "T" blocks when in their flattest orientations. This is almost better, because I am not changing the sprite and the color at the same time on any scanline. It might not even be possible to have that many changes on one scanline...imagine where both players have a T block on the same line...it might be too many things to change. I'm not using VDELPx *yet*, though I do have that at the ready when necessary.

 

Here was the old output (again) of a strange double "T" block test...you can ignore the "fake" duplicated sprite because it was just something in there for testing:

 

post-66218-0-03975100-1540491063.png

 

Each color change going down is simply decrementing the color value. Starting with a specific color value for the first color causes a nice single-scanline edge gradient at the top and bottom. I still need to draw the other two rotations, and I should probably avoid changing NUSIZx too much (if at all), because that will cause some off-by-one pixel positioning issues which could get really annoying...

 

As it stands right now, drawing the "T" block is simply a matter of changing from 3 to 1 pixel with a color change decrement each line, and the other two vertical orientations will have a 1 pixel block of scanlines, changing to 2 pixels, and then back to 1. (Recall that these are using quad-sized player objects.) Color changes would be a little less frequent for those two orientations and could be moved out of the way of the simple sprite changes if necessary.

 

Nothing too difficult, so lets get a "T" block moving down the screen next...and iron out the graphics for the vertical rotations...

Edited by AkashicRecord
Link to comment
Share on other sites

Well, that was fun. I need to completely revise the drawing strategy for these game pieces if this is going to be dynamic and flexible. I'm leaving a silly "easter egg" in this one which converts the "T" block into a powerful attack spaceship with an ion beam! ;)

 

T-BLOCK-anim.bin

 

There are way too many extraneous variables and waste in this one, but I needed to get an idea of how to structure the drawing and color changes for this stuff to cut down on code and CPU. Since I'm going to have the horizontal positioning be one of the first things that I do in VBLANK, I think I'll be able to squeeze everything in, though I may just need to settle on (occasional) table lookups after all...

Edited by AkashicRecord
Link to comment
Share on other sites

Converting to code, I stumbled upon a slightly different way to shade the "T" blocks when in their flattest orientations. This is almost better, because I am not changing the sprite and the color at the same time on any scanline. It might not even be possible to have that many changes on one scanline...imagine where both players have a T block on the same line...it might be too many things to change. I'm not using VDELPx *yet*, though I do have that at the ready when necessary.

 

Here was the old output (again) of a strange double "T" block test...you can ignore the "fake" duplicated sprite because it was just something in there for testing:

 

post-66218-0-03975100-1540491063.png

 

Each color change going down is simply decrementing the color value. Starting with a specific color value for the first color causes a nice single-scanline edge gradient at the top and bottom. I still need to draw the other two rotations, and I should probably avoid changing NUSIZx too much (if at all), because that will cause some off-by-one pixel positioning issues which could get really annoying...

 

As it stands right now, drawing the "T" block is simply a matter of changing from 3 to 1 pixel with a color change decrement each line, and the other two vertical orientations will have a 1 pixel block of scanlines, changing to 2 pixels, and then back to 1. (Recall that these are using quad-sized player objects.) Color changes would be a little less frequent for those two orientations and could be moved out of the way of the simple sprite changes if necessary.

 

Hey Akashic, I've been reading this thread with much curiosity (even if it does tend towards information overload ;-) ), and I just wanted to weigh in to say that the above screenshot of the playing pieces with the code-based gradient that you devised looks gorgeous, and much better than the original mockups that you posted. Here's hoping that it is actually possible to achieve in the finished game without compromises/sacrifices in other areas. Keep up the amazing work, I think that this title is going to turn out epic in the end.

Edited by NostAlgae37
  • Like 1
Link to comment
Share on other sites

Hey Akashic, I've been reading this thread with much curiosity (even if it does tend towards information overload ;-) ), and I just wanted to weigh in to say that the above screenshot of the playing pieces with the code-based gradient that you devised looks gorgeous, and much better than the original mockups that you posted. Here's hoping that it is actually possible to achieve in the finished game without compromises/sacrifices in other areas. Keep up the amazing work, I think that this title is going to turn out epic in the end.

Thanks for the comment! I know it is a lot of technical mumjo-jumbo, but this works really well for me as a detailed note-taking system. I won't miss anything if its well-documented. :)

 

I think I'll absolutely be able to hit my target...it's getting to be within sight already. :D

 

I hope to have an animated example with that gradient shading added back in later. (I took it out to simplify testing for now, but I have some test files that still have it in.)

 

One of the upcoming protoypes will have more pieces that will change in response to button presses. I'd like to move on to that before rotations and the game coordinate system.

Link to comment
Share on other sites

 

Hey Akashic, I've been reading this thread with much curiosity (even if it does tend towards information overload ;-) ), and I just wanted to weigh in to say that the above screenshot of the playing pieces with the code-based gradient that you devised looks gorgeous, and much better than the original mockups that you posted. Here's hoping that it is actually possible to achieve in the finished game without compromises/sacrifices in other areas. Keep up the amazing work, I think that this title is going to turn out epic in the end.

 

This isn't exactly what I had in mind for the finished product, but it gets kind of close. I'm still cranking hard on this stuff, but I don't feel bad about tossing out crude examples in the meantime. This one chunks a purple T block down the screen, and looks a bit better than the previous:

 

T-BLOCK-anim2.bin

 

Here's a simulated screen image:

 

post-66218-0-40320700-1540584491.png

 

And here's a "badly adjusted" simulated TV image (running under Stella):

 

post-66218-0-67284500-1540588606.png

 

(I know it isn't much....because I'm not showing everything just yet...)

Edited by AkashicRecord
  • Like 1
Link to comment
Share on other sites

Here's another dump of some (rather obsolete) graphics tests using the gradient shading:

 

post-66218-0-69288300-1540613872.png

Z-BLOCK-anim.bin

 

post-66218-0-14200400-1540613877.png

S-BLOCK-anim.bin

 

post-66218-0-79621900-1540613883.png

J-BLOCK-anim.bin

 

Again, it isn't much, but it gives a gist of what this might look like. This code is NOT tested on real hardware, so I have no idea what it looks like on a real television and console.

 

The joystick is still enabled for these. Use the left and right stick inputs to randomize the playfield color every ~30 frame ticks, and use the up and down inputs for fine-tuning the color gradient. It's good for testing to see what the game pieces look like against other playfield colors...

Edited by AkashicRecord
  • Like 1
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...