Jump to content

AkashicRecord

Members
  • Content Count

    208
  • Joined

  • Last visited

Everything posted by AkashicRecord

  1. 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...
  2. 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. 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: 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...
  3. 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...
  4. 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.
  5. 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.
  6. 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...)
  7. 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.
  8. 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...
  9. 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.
  10. 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...
  11. 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: 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...
  12. 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...
  13. 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.
  14. ....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.
  15. 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. 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...
  16. 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.
  17. 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.)
  18. 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.)
  19. Atari was actually behind the Tengen Tetris that was banned and pulled from the market over licensing issues with Nintendo. That's my primary inspiration for this one, but it will be quite different.
  20. Oh, here's an old idea that I was toying with as I was testing the vertical animation strategies, but I didn't bother to share it. I had an idea to have special pieces (especially in some 2P modes) that do different things. One idea I had was to cycle the colors on the special pieces kind of like this: colorcycle-test.bin It's not perfect, but I kind of liked the simplicity of the effect. I could also have unfinished lines in the game that randomly light up and color cycle for some amount of time.
  21. I'm going to reattach an image from my early playfield tests a few pages back. This is close to what I'm aiming for (with a progression of colors), but the image has some glitches due to bugs. I'll try to get a bin that cycles through some colors in this fashion:
  22. So while this self-executing data from RAM idea is very nice and elegant, I'm going to simplify things first and press on with the more naive method(s) for checking for clear lines, etc. There's no sense in complicating the prototyping process too much, too soon... As far as the playfield is concerned, I still think it is very nice to have the data representation in the exact form that the PF1 and PF2 registers will require, so that is going to be a large focus today. The majority of the game logic is just a few simple bitwise operators and bit tests (for the most part). Translating the game field coordinates into scanlines (and horizontal positioning code) is probably the most complicated and complex issue... I'm also looking again at the design of the playfield. The shaded blue 2-player image a few pages back still looks the best to me. I'll probably put up a simple .bin later that draws that. Somehow I b0rked the assembly file for that one days ago, so I have to rewrite it.
  23. Here's another .bin, but the appearance won't exactly show what is actually happening under the hood... You'll.probably have to use Stella's debugger to see what is going on towards scanline 257. This is the first test where a small number of bytes are manipulated in RAM as part of a seed for a dynamic self-executing mini-kernel. Right now, this doesn't actually perform anything "dynamic," but it does jump to some code that is written to RAM which performs a spurious operation (CPX #$E0) and then jumps back to code which rebuilds itself (i.e.; the RAM jump that was just returned from.) ramjump-test.bin
  24. He found the prototype cartridge in a box decades later...
  25. Really? I was referring to a reflected, or mirrored playfield which should go in the order of: PF0 PF1 PF2 PF2 PF1 PF0 So I thought that was why there was this cycle 48 contention for PF2 in this mode, because you have to write to PF2 at exactly the same time that it is being read (and essentially locked) for the first time...and that you only have 1 specific cycle in which this can be accomplished, because it is immediately read again for a second time. In a sense, it almost seems that you shouldn't even have a cycle to do this, but somehow you do... I don't need to get hung up on the absolute specifics, but it does help to understand why certain things are the way they are, especially if you have a hunch.
×
×
  • Create New...