Jump to content
jlew715

Questions from a newbie - simple color and animation

Recommended Posts

Hey all,

 

I tried to spend the weekend learning the basics (ha!) of IntyBasic. And what better way to learn for a "retro" console than to make a PONG clone? So I made a very rough PONG clone called "PONGadelic" to learn:

  1. Simple sprite definition and rendering.
  2. Controller input and translating input to sprite movement.
  3. Simple collision detection.
  4. How to handle color-switching on the Inty.

I've attached the BAS and ROM files for your perusal. The PONGadelic_title.BAS simple renders the classic title screen (adapted from the SDK's classic title screen example - thanks!).

 

So down to my questions - I've got the Inty in ColorStack mode:

  • MODE   SCREEN_COLOR_STACK, STACK_BLACK, STACK_CYAN, STACK_BROWN, STACK_YELLOW 'I have no idea how to use anything after STACK_BLACK
    BORDER BORDER_BLACK

This results in my entire play field being BLACK, which is what I want for now. Great. But say, after either player scores a point, I want to change the whole play field to the next color in the stack - that is everything that was STACK_BLACK should now be STACK_CYAN. I was not able to figure out how to accomplish this. Is there some sort of "advance color stack to next color" command? I saw something about setting $2000 but I'm not sure how or where to do that. I don't want to change the color of a sprite or printed object; I want to make the entire play field a new color.

 

 

 

Second question - I have a Ball object (SPRITE 6) that I want to animate in a simple, back-and-forth kind of deal. I have two sprites loaded into GRAM for this purpose; SPR03 and SPR04.

SPRITE 6,ballX+HIT+VISIBLE,ballY+ZOOMY2,SPR03 + ballColor 'this is where Id like to animate the ball, (i.e. change to SPR04 for X frames, wait X frames, then change back to SPR03).

My assumption is we need some kind of counter that switches the line from using SPR03 to SPR04 every X frames, then starts over and switches back to SPR03 after X frames elapse again - but I struggled with how to implement this. When I had counters swapping the sprites, I ran into collision detection issues.

 

 

Final question - WAITs - I don't really understand when I should (and shouldn't) be using them. I understand that certain things need to "settle" sometimes, or you can only do certain operations once every "cycle"... but I'm kind of lost :? .

 

 

Besides those (probably obvious!) questions, PONGadelic is a totally functional albeit rough PONG clone! If you feel like trying it out, here's how it works:

  • Classic PONG - use your paddle to bounce the ball and prevent it from going out the back of your side.
  • Left Controller - Left Side; Right Controller - Right Side.
  • Player who just gave up a point gets to "serve" the ball using any of the Side Buttons (serving merely sends the ball in a random direction from the center).
  • When the game first starts, Left Player gets to "serve".
  • First player to 9 points wins the game.
  • Walls, Paddles, and Ball have a random color during each round of the game (hence PONGadelic).

 

Thanks in advance for your help!

J. Lewis

 

 

pongadelic_title.bas

pongadelic.bas

constants.bas

pongadelic.rom

Edited by jlew715

Share this post


Link to post
Share on other sites

Hi, there,

 

I just tried out your game for a round and it looks very cool. Great job!

 

Here are some answers to your questions:

  • Background Color: The Color Stack is a bit complex to describe. I recommend you read this brief description I gave in the past to at least get an idea of how it works. In the meantime, you are in luck! It turns out that for your immediate purpose, you do not need to learn the Color Stack at all, all you need to do is change the first color in your MODE statement to "STACK_CYAN". This is because you are only using a single background color. Issuing a new MODE statement with the new color should update your entire screen automatically without having to clear it or anything.

    If you want to know how or why this works, just ask. I just didn't want to bombard you with technical information if you are not seeking it.
MODE   SCREEN_COLOR_STACK, STACK_CYAN, STACK_CYAN, STACK_BROWN, STACK_YELLOW
  • Sprite Animation: This question is related to the next one and it depends on how you set up your main game loop. Perhaps it would be easier if you tell us how you tried to do it before and how it failed; and we may be able to suggest how to fix it.

    You should check out some of the sample projects and contributions included with the IntyBASIC SDK for examples on how to animate sprites.

 

  • WAIT Use: The Intellivision video chip (STIC) is directly connected to video and Graphics RAM (GRAM), and "owns" the graphics bus, to which both are connected. The STIC controls the drawing of the video frame and generates the TV signal to draw it on the screen. However, access to the STIC registers (where you manipulate sprites) and GRAM (where you draw custom graphics) is only available during a brief period when the TV raster is resetting after drawing a full frame. This is called "Vertical Blanking" or VBLANK. The VBLANK period then is a regular event which occurs every 1/60th of a second on NTSC units and 1/50th of a second on PAL units.

    The Intellivision issues a hardware interrupt -- a signal that interrupts the CPU and lets it handle an external event -- whenever the VBLANK period occurs. The console is hard-wired to call an internal "Interrupt Service Routine" (ISR) which is intended to take action and update the STIC and GRAM as necessary. When the VBLANK interrupt arrives, the CPU automatically saves its internal state, calls the ISR (which does whatever it needs to do), then returns to the CPU which restores its state and continues along. In this way, it is a sort of "multi-tasking," except that you do not get to control its schedule.

    The VBLANK interrupt, being so regular, also serves as a handy source for timing. We tend to time our games in terms of TV frames per second precisely because the VBLANK conveniently alerts us every 1/60th of a second. Thus, a game loop which does all its work to prepare one game cycle, then waits for VBLANK before doing it all over again, will run once every 60th of a second, or at 60 fps.

    IntyBASIC has its own ISR to do its work. It "buffers" all your sprite and GRAM changes into memory and when the VBLANK interrupt arrives, poof!, the ISR posts all those changes to the STIC and GRAM in one blow. Well, at least it tries to do everything it can, since like I mentioned above, the VBLANK period is brief, consisting of just a few thousand cycles.

    You cannot control when VBLANK occurs, it always happens on its own and it's linked to the TV signal timing. When you use IntyBASIC, you do not control the ISR directly either. However, what you can do is wait for it. That's what the WAIT command gives you: it tells IntyBASIC, "OK, I'm done with stuff for this frame, so we just wait for the next VBLANK ISR and continue later." In turn, IntyBASIC will make a "busy wait," that is, it will just loop without doing any work, just waiting for the interrupt to come.

    That's it, that's the mystery of the WAIT command. Now, how do you use it?

    Well, that's entirely up to you, but here are a few tips:
    • A game loop has typically one or two WAIT statement. They mark how many frames it takes to execute one single cycle of your game. Fast action games typically try to do everything within a single frame to run as fast as possible, and so would use at most one single WAIT. However, there is no rule. Just know that the more WAIT statements in your game loop, the more TV frames it takes to complete a single cycle, and the more sluggish or unresponsive your game may appear.

      For the sake of comparison, consider that the original Mattel Intellivision titles used a game engine that used three frames for each game cycle, resulting in a game running at 20 Hz. If you ever felt that the old classic titles were a bit sluggish, this is why. In contrast, most home-brews run at 60 Hz or 30 Hz, and consequently feel much more snappy.
    • Game initialization routines are not time-bound -- that is, they do not need to be super fast (i.e., the user can wait a few milli-seconds for the level to start and he won't even care). Therefore, their timing is not really critical. Typically, during initialization, games spend an entire frame just loading as much GRAM as they can, then perhaps another one or two frames drawing the screen and setting everything up, and maybe a few more just to get ready for action. You can split your initialization routines into "phases" or "steps" using WAIT statements in between each one. When the entire thing is done, you jump into your game loop.
    • The typical game loop does all its time-critical stuff first (STIC/MOB and GRAM updates), then updates the state of the game. Here's a simple description of this I wrote in another post. Note again that there are no rules, so its really up to your own design.
    • Remember that for commands like SPRITE, MODE, BORDER, etc. IntyBASIC actually "buffers" them for you. That is, it keeps track of the requests and actually applies them within the ISR on the next VBLANK interrupt. Collisions also are read during the ISR, since they are a function of the STIC and because they are a reaction to sprite movements which also happen during VBLANK.

      This is very important to know and understand. It means that whatever you are doing during your game loop is a reaction to whatever happened in the previous one. For instance, if you move a sprite in one frame, the collisions will not get detected until the next frame, after the ISR runs and checks the STIC for collisions. Likewise, any updates to your sprites in one frame, will not get posted to the STIC until the next one, when the ISR executes.

      What this means is that your game loop is not drawing the current frame, but setting up the next one. You should keep this in mind when you write your game loop. You can then think of your loop like this:
      • Critical stuff (fresh after VBLANK triggers):
        • Draw sprites
        • Draw graphics
        • Check collisions
      • React to previous frame:
        • Update state based on collisions (e.g., game over, new level, player death, etc.)
      • Compose next frame:
        • Set up graphics
        • Set up sprite updates
        • Set up screen updates
      • Wait for VBLANK and do it all over again

 

I hope the above helps. Feel free to ask questions. I'm sure others can offer sample code and other insight. Remember, there isn't one single way of doing anything, but it helps employing techniques others have used successfully. :)

 

-dZ.

Edited by DZ-Jay
  • Like 1

Share this post


Link to post
Share on other sites

I'll just add a little to what DZ-Jay has already said.

 

Advancing the color stack is not the right solution to change the whole background of the screen. That said, if you want to understand what advancing the color stack is just for some self-education, you can check out a little program called Color Stack Fiddler. It lets new programmers manually adjust various features of the STIC chip in Color Stack mode, including Advancing the Color Stack. You can run the program, look at its IntyBASIC source code, or just watch the animated GIF to get an idea of what the STIC is capable of.

http://www.atariage.com/forums/topic/285618-color-stack-fiddler

  • Like 1

Share this post


Link to post
Share on other sites

As always, DZ-Jay, a fantastic and detailed response. This was very helpful and I was able to get my WAITs figured out!

 

I was able to figure out the animation as well - the issues I encountered before were due to an extra BITMAP line in one of my sprites (counting to 8 is hard). My original approach worked once that was resolved!

  • Like 1

Share this post


Link to post
Share on other sites

As always, DZ-Jay, a fantastic and detailed response. This was very helpful and I was able to get my WAITs figured out!

 

I was able to figure out the animation as well - the issues I encountered before were due to an extra BITMAP line in one of my sprites (counting to 8 is hard). My original approach worked once that was resolved!

 

Awesome! I'm glad I could help. :thumbsup:

 

-dZ.

Share this post


Link to post
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.

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...