In this episode we learn how to creating player graphic animations and using pointers to simplify your code.
Released:
February 1, 2022
Original Link:
https://youtube.com/watch/IGq992JnK1Q
Your support is greatly appreciated! https://www.patreon.com/8blit
welcome to eight blit a channel to discover how you can make games for the 8-bit atari video computer system from 1978. in this episode we’ll explore how to do animation that can be applied to your player and missile graphics so let’s get started and kick off season two well it’s possible to create a game that features no graphic animation at all as we can plainly see here with the game pong and again in the game miniature golf in both games the only movement on the screen are the objects themselves but in this pong’s execution still works because it involves risk and skill miniature golf though really is quite boring incorporating even just a couple frames of animation can add a lot of personality and charm to the game as we can see here in the game bump and jump the animation on the cars tires adds a ton of movement to the screen making it more lively and exciting however i think my favorite animation comes from the game demon attack the flapping along with the colors and the movement keep the screen exciting even when you’re down to just one demon left animation on the atari 2600 is basically no different than on tv and movies it’s simply a series of two or more pictures that are slightly different and showing them in sequence one after the other it could be a spaceship exploding a man running or fire burning let’s start simple with a screen and a single non-animated ghost
first we’ll open up the sprite editor in the atari dev studio you can learn more about that in our previous episode called code faster with the atari dev studio i’ll include a link in the description
we’ll create two frames for the ghost and export the code to use in our program these two frames will be used in all the examples in example one we’ll use the same code we used in the previous episode called more sprites in color again i’ll include the link in the description the important part of this code is how we’re loading which line of the graphic to display on our scan line you can see here we’re loading a value located at the index given in the y register starting at the memory address represented by ghost f0 ghost f0 is actually a static hard-coded value that the assembler will replace with the real memory address of the graphic when it’s building the binary rom file if we look at the actual opcode the assembler generates we can see that our load instruction is the hex value b9 well the address the ghost graphic is located at is 72 f0 as represented in little indian form where the least significant bit is stored before the most significant bit a more human readable form of this address would be f072 which is what you’ll see in a debugger we’ll have a video on debugging coming up so make sure you subscribe and click the notification bell so you’ll always know when the new video is up what we need to swap the two frames of our graphic is a way to change the memory address that’s used when loading our graphic to accomplish this we’ll use something called a pointer pointers can be a little difficult to understand when you first encounter them in programming but the concept is simple typically you would store a value in a byte of ram like the number of players in a game or how many missiles you have left a pointer doesn’t hold a value it holds a memory address pointing to where the value is when you use a pointer you won’t get the number of players or remaining missiles you’ll get the address where you can find these values first we’ll need to reserve two bytes for our pointer this will ensure that the assembler will not use those two bytes for anything else in this particular case our pointer will use the two bytes located at the addresses 84 and 85. then we’ll use the assembler to get the least significant byte of the 16-bit address where the ghost graphic resides and store it in the first byte we defined for our pointer then pull the most significant byte of the address and store it into the second byte of the pointer in ram this would look like this with the address 84 containing the least significant byte value of 72 and address 85 containing the most significant byte value f0
then in our load instruction we use brackets around our pointer which tells the assembler that we want to use the indirect load value opcode to get the value located at the memory address found in the two bytes located at the pointer address the indirect load value instruction is assembled with the opcode of b1 and the address of the pointer is at the address 84. the b1 opcode will use the values stored in the memory addresses 84 and 85 as the 16-bit ram address now we’re no longer using the static address of the ghost graphic in our load routine and when we execute our code our ghost is still with us we have our code using our pointer address to draw our graphic let’s use that to swap which ghost frame we’re going to draw we could swap our graphics for every screen frame but that would swap them so fast that you wouldn’t be able to see the animation it would just look like the ghost is flickering which can be used for other game mechanics like in miss pac-man when the ghosts are returning to their non-edible form for our purposes we’re going to swap the ghost frame every 8 screen frames we’ll start by creating a variable to hold which screen frame we’re currently showing next we’ll add a bit of logic to flip which frame of animation will use every eighth screen frame the algorithm we’ll use will count up to 16 and return zero for the first eight screen frames and one for the rest then the screen frame counter will reset back to zero to do it all over again we start by increasing the current value of the screen frame in memory by one and then load it into the accumulator now we’ll use the and instruction to and the value 15 with the screen frame we just loaded into the accumulator this will reset the count back to zero if the screen frame is above 15. otherwise it will return the value 0 through 15. now that we know our screen frame is within 0 through 15 we’re going to shift the bit of our accumulator value to the right using the lsr instruction we’ll use a screen counter of seven as an example in binary seven would be represented as zero zero zero zero zero one one one shifting the bits to the right drops off the very first bit resulting in zero zero zero zero zero zero one one which is equal to three in decimal to make this more useful for our purposes we’ll need to reduce it down a little more by shifting the bits to the right two more times this will leave us with a value of zero which indicates we will use the first frame of the graphic animation if our screen frame counter was eight that would give us a binary equivalent of zero zero zero one zero zero zero and then when shifted right three times leaves us with a value of one which indicates that we’ll use the second frame of the graphic so screen frames 0 to 7 will result in 0 using the first frame of the animation and 8 to 15 will result in a 1 using the second frame now we can use our branch to jump to which graphic frame we want to assign to the pointer this part works the same as the previous example except for some duplicated code we used to set up our pointer we’ll take care of that shortly running the code we have a nicely animated ghost so now our code can flip between animation frames based on the timing we created and we have our logic to determine which frame we’re going to display however this implementation is a little messy when we look at that part of the code the good news is that we can move that part of the code and set it up during assembly for this we’re going to create a couple of data tables to store the least and most significant bytes for both of our graphic animation frames now when we assign the pointer we can use the load instructions index parameter to pull the graphics frame from the data table since our algorithm to calculate which graphic to use results in either a 0 or a 1 this works nicely for selecting the index from the data table this change removes the branch and our jump from the previous example saving us a bit of time and making the code more readable running the new code he’s still there hovering just a bit more efficiently let’s tweak the code a little and give him a friend
once again we’ve covered a lot of information in this episode and all of the examples are available on our github which i’ll link to in the description you can follow along on social media and our website there’s not a lot at the moment but once i figure it all out you can be sure i’ll start posting more information behind the scenes details and a little history if you found the video interesting i’d appreciate it if you hit that like button and share and let others know and if you haven’t already done so please consider subscribing to the channel and hit the bell icon to make sure you’re notified when a new video comes out if you like to help support the development of the channel please consider becoming a patron a link to that in the description as well that’s all for now thanks for watching and i’ll catch you later
Back to top of page