Jump to content
IGNORED

Player animation.


STGraves

Recommended Posts

I looked at the code in the old main loop and see nothing that is supposed to fix anything with the screen:
_

main
   COLUBK = $8A
   pfcolors:
   $40
   $42
   $46
   $48
   $4A
   $4C
   $4E
   $4C
   $4A
   $48
   $46
   $42
   $40
end

   if joy0up || joy1up then pfscroll down
   if joy0down || joy1down then pfscroll up
   if joy0right || joy1down then pfscroll left
   if joy0left || joy1left then pfscroll right
   
   rem This is the animation function
animate
   rem This frame variable slows down the animation
   v = v + 1
   rem This code animates the sprites
   if v = 7 && w = 0 then ax
   if v = 7 && w = 1 then bx
   if v = 7 && w = 2 then cx
   if v = 7 && w = 3 then dx

   goto nextstep

   
   rem These four sprites are different stages of the animation

ax
   v = 0
   w = 1

   player0:
   %01110000
   %00110111
   %00011111
   %10011111
   %11111111
   %00011111
   %00001111
   %00000011
   %11000011
   %11111111
   %10011111
   %11111100
end

   goto nextstep
   
bx
   v = 0
   w = 2
   player0:
   %01110000
   %00110111
   %00011111
   %10011111
   %11111111
   %00011111
   %00001111
   %00000011
   %00000011
   %00000011
   %11000011
   %11111111
   %10011111
   %11111100
end
   goto nextstep

cx
   v = 0
   w = 3
   player0:
   %00000111
   %01110011
   %00011111
   %10011111
   %11111111
   %00011111
   %00001111
   %00000011
   %00000011
   %00000011
   %00000011
   %00000011
   %11000011
   %11111111
   %10011111
   %11111100
end
   goto nextstep
   
dx
   v = 0
   w = 0
   player0:
   %00000111
   %01110011
   %00011111
   %10011111
   %11111111
   %00011111
   %00001111
   %00000011
   %00000011
   %00000011
   %11000011
   %11111111
   %10011111
   %11111100
end
   goto nextstep
   rem Create acorn sprite

nextstep
   player1color:
   $06
   $00
   $00
   $00
   $00
   $00
   $0C
   $00
   $00
   $00
   $00
   $00
   $0A
   $0A
   $0A
   $0A
   $0A
   $0A
   $0A
   $0A
end

   player1:
   %01100110
   %00100100
   %00100100
   %00100100
   %00111100
   %00111100
   %10000001
   %10111101
   %10111101
   %10111101
   %10100101
   %01100110
   %00011000
   %00100100
   %01111110
   %10000001
   %10000001
   %01111110
   %00111100
   %00011000
end
   

   rem check to see if a missile has already been fired
checkfire
   if bally>100 then goto skip
   bally = bally - 2 : goto draw
   rem if a missile hasn't been fired, then fire missile
skip
   if joy0fire || joy1fire then bally=player1y-2:ballx=player1x+4

   rem Draw output to screen
draw
   drawscreen

   rem Fix player wraparound bug
   if player1x < 8 then player1x = 8
   if player1x > 150 then player1x = 150
   if player1y < 8 then player1y = 8
   if player1y > 84 then player1y = 84

   rem Have player 1 chase player 2
   
   if player0y < player1y then player0y = player0y + 1
   if player0y > player1y then player0y = player0y - 1
   if player0x < player1x then player0x = player0x + 1
   if player0x > player1x then player0x = player0x - 1
   player0x = player0x : player0y = player0y


   rem Detect missile collision with squirrel
   if collision(ball,player0) then score=score+1:player0x=rand/2:player0y=0:bally=255:goto pointsound
   rem Detect squirrel collision with the acorn
   if collision(player1,player0) then score=score-1:player0x=rand/2:player0y=0:bally=255:a=a-1:goto deadsound

   rem joystick movements
   if joy0up || joy1up then player1y = player1y-1 : goto skipmove
   if joy0down || joy1down then player1y = player1y+1 : goto skipmove
   if joy0left || joy1left then player1x = player1x-1 : goto skipmove
   if joy0right || joy1right then player1x = player1x+1 : goto skipmove

   rem refresh the screen
skipmove
   goto main

_

Can you point out what you think is supposed to fix the problem that I didn't move over to the new code?

Link to comment
Share on other sites

Yeah..I added that a few days ago to fix up the scrolling. Animating characters is pretty easy and fun, though! I use variables!

 

Just declare a variable (a=a+1) and then

 

if a=0 then player1:

*frame

 

if a=10 then player1:

*next frame

 

if a=20 then player1:

*next frame

 

and so on..

 

Also..if the colors in each frame are the same, you only need to declare them once (otherwise you'll be wasting a TON of RAM). So after you declare your colors then set up your sprite frame by frame with a variable to time them. Adjust the variable count to change the speed of the animation and then end it later with a count killer, like

 

if a=30 then a=0

 

This is easy and works great.

Edited by Papa
Link to comment
Share on other sites

Yeah..I added that a few days ago to fix up the scrolling. Animating characters is pretty easy and fun, though! I use variables!

 

Just declare a variable (a=a+1) and then

 

if a=0 then player1:

*frame

 

if a=10 then player1:

*next frame

 

if a=20 then player1:

*next frame

 

and so on..

 

Also..if the colors in each frame are the same, you only need to declare them once (otherwise you'll be wasting a TON of RAM). So after you declare your colors then set up your sprite frame by frame with a variable to time them. Adjust the variable count to change the speed of the animation and then end it later with a count killer, like

 

if a=30 then a=0

 

This is easy and works great.

People usually graduate from that kind of thing to using on ... goto like you can see in these programs:

 

atariage.com/forums/topic/235427-tinkernut-world-deluxe-example-program/

Link to comment
Share on other sites

Yeah.. Like what I just said isn't a RAM efficient way to animate! I know it works great and you haven't done anything that shows me that you've 'graduated' beyond anything that I've done!

 

Show me a game with more animation than mine from BB?

Link to comment
Share on other sites

Yeah.. Like what I just said isn't a RAM efficient way to animate! I know it works great and you haven't done anything that shows me that you've 'graduated' beyond anything that I've done!

 

Show me a game with more animation than mine from BB?

It has nothing to do with me or your overinflated ego. The better programmers who pop in once in a while to teach us stuff show us better ways to do things. They usually recommend the on ... goto method shown in the programs I mentioned.

Link to comment
Share on other sites

There is no better way to animate using BB with as many sprites as I use. There is no simpler way, either! I use goto, and the 16-bit randomizer, on a 32K bankswitched game!

The only overinflated ego I see here is yours! Using a variable timer is as base level as it gets! There are several frames of animation per character in my game and it requires the ability to control the timing of each sprite frame change. There is no better way than using a controlled variable. Now you've attacked my ability to program, like I haven't programmed PC games that are more advanced than even this! You don't know me, and you seriously have no idea who your talking to if you think I haven't 'graduated' into advanced enough programming for simple animation! You've insulted me by acting like you're superior to me, and that IS the sign of an over inflated ego. You wrote the guys code for him while I explained HOW to do it himself in a way that uses the least amount of RAM and gives him complete control over the timing of the frame!

Link to comment
Share on other sites

For fun, let's look at the disassembly of both methods and compare them. I'm sure Papa already knows all this, but for the rest of us it should be educational.

 

Method #1 (Chained IF statements)

  if a=0 then l1
  if a=1 then l2
  if a=2 then l3
  if a=3 then l4

produces

LDA $D6
CMP #$00
BEQ l1
LDA $D6
CMP #$01
BEQ l2
LDA $D6
CMP #$02
BEQ l3
LDA $D6
CMP #$03
BEQ l4

If the last branch is taken the total cycles consumed will be 4 LDA ZP (3), 4 CMP (2), 3 BEQ-not taken (2), 1 BEQ-taken (3) for a grand total of 29 cycles. This could have been reduced to 20 if the compiler was a little smarter about omitting the redundant loads. Another observation is that this code runs in O(n) time. In other words, the more if statements you chain the more valuable CPU cycles you consume. The other problem is the loss of ROM space. It takes 6 bytes to add the LDA/CMP/BEQ instructions for each if statement.

 

Method #2 (on ... goto)

on a goto l1 l2 l3 l4

Produces:

LDX $D6
LDA MSB_Lookup,X
PHA
LDA LSB_Lookup,X
PHA
RTS

*MSB_Lookup and LSB_Lookup each contain a byte per label in on ... goto construct


In all cases the total cycles consumed will be 1 LDX ZP (3), 2 LDA Absolute,X (4), 2 PHA (3), 1 RTS 6 for a grand total of 23. What is even more interesting is that the code runs in O(1) time. In other words, it's going to take 23 cycles regardless of how many labels you have. An added bonus is that each new label will only use 2 bytes of ROM to expand each lookup table by a byte.

 

So in conclusion, using the on...goto method is the better solution when efficient use of CPU is important. I'd also like to point out that both methods only dealt with a single variable. So I don't understand the claim that it will use less RAM. None of this should come as any surprise since RT generally provides sound advice based on many years of experience with bB.

 

If any bB programmers found this interesting or usefull let me know. I may consider creating a blog where I analyze different commands periodically.

  • Like 4
Link to comment
Share on other sites

but I think Papa is right about the colors, put them in a subroutine and don't set

them if you don't need to.

Right, I was just talking about all of the if-thens. Nobody is saying that we need copies of the color data with each animation frame (unless the colors change with each fame :D ).

 

Speaking of color data, in an earlier version of the program in this thread (and in a test program), if the color data for multicolored player0 wasn't put in the main loop or called in some way, the player0 sprite would sparkle like it was on fire. That happened when scrolling and using "set kernel_options player1colors playercolors pfcolors". Here's an example:

 

sparkle_sprite.bin

Link to comment
Share on other sites

I use certain animation that loops back and forth and must have multiple variables. I was quoting 'the book' for the the programmer. I'm also pretty sure that answering in assembly isn't going to help this beginner with ease of use, or help to explain how to stop the sprite! Ease of use does calculate into efficiency, in my opinion.

Link to comment
Share on other sites

on a goto l1 l2 l3 l4

Produces:

LDX $D6
LDA MSB_Lookup,X
PHA
LDA LSB_Lookup,X
PHA
RTS

*MSB_Lookup and LSB_Lookup each contain a byte per label in on ... goto construct


In all cases the total cycles consumed will be 1 LDX ZP (3), 2 LDA Absolute,X (4), 2 PHA (3), 1 RTS 6 for a grand total of 23. What is even more interesting is that the code runs in O(1) time. In other words, it's going to take 23 cycles regardless of how many labels you have. An added bonus is that each new label will only use 2 bytes of ROM to expand each lookup table by a byte.

 

So in conclusion, using the on...goto method is the better solution when efficient use of CPU is important. I'd also like to point out that both methods only dealt with a single variable. So I don't understand the claim that it will use less RAM. None of this should come as any surprise since RT generally provides sound advice based on many years of experience with bB.

 

If any bB programmers found this interesting or usefull let me know. I may consider creating a blog where I analyze different commands periodically.

 

 

but of course you should gosub to the on goto and then return

(if you just have to use on goto) instead of that jump there then

jump back nonsense, and that will cost something ;)

 

 

re a blog, a tabulation and comparison of different techniques would

be usefull but it could get complicated

(eg if it were me I'd probably put the sprites in a data statement)

Edited by bogax
Link to comment
Share on other sites

I use certain animation that loops back and forth and must have multiple variables. I was quoting 'the book' for the the programmer. I'm also pretty sure that answering in assembly isn't going to help this beginner with ease of use, or help to explain how to stop the sprite! Ease of use does calculate into efficiency, in my opinion.

I'm not exactly sure what you mean by loops back and forth. Could you provide an example? I do agree with you on keeping the code simple when possible. Also, I'm not trying to say that the method you suggested is wrong or worse. I just thought it would be interesting to analyze them more in depth and figured why not share my findings.

 

 

 

but of course you should gosub to the on goto and then return

(if you just have to use on goto) instead of that jump there then

jump back nonsense, and that will cost something ;)

 

 

re a blog, a tabulation and comparison of different techniques would

be usefull but it could get complicated

(eg if it were me I'd probably put the sprites in a data statement)

I was thinking it would be more focused on the "how it works" rather than "which is better".

Link to comment
Share on other sites

I'm not exactly sure what you mean by loops back and forth. Could you provide an example? I do agree with you on keeping the code simple when possible. Also, I'm not trying to say that the method you suggested is wrong or worse. I just thought it would be interesting to analyze them more in depth and figured why not share my findings.

 

I was thinking it would be more focused on the "how it works" rather than "which is better".

 

 

Which is better would be for the individual programmer to decide

but there's generally several ways to do something with different

timing and space requirements

I think it would be a shame to just exposit on different methods

without providing some analysis (and tabulation of) timing and space so that

a programmer could see the trade offs

(and after all that analysis is what you were just doing)

Link to comment
Share on other sites

. . . but there's generally several ways to do something with different timing and space requirements . . .

Speaking of similar stuff, SeaGtGruff started listing cycle count information for various things before he got too busy or lost interest or both:

 

http://www.randomterrain.com/atari-2600-memories-batari-basic-commands.html#cycle_count_goto

http://www.randomterrain.com/atari-2600-memories-batari-basic-commands.html#cycle_count_gosub

http://www.randomterrain.com/atari-2600-memories-batari-basic-commands.html#cycle_count_addition

http://www.randomterrain.com/atari-2600-memories-batari-basic-commands.html#cycle_count_division

http://www.randomterrain.com/atari-2600-memories-batari-basic-commands.html#cycle_count_bitop

 

(If those links don't hop to where they are supposed to, just refresh/reload the page.)

 

It would be nice to have more cycle count subsections on the bB page.

 

It would also be nice to have a new section or subsection that lists the cycle count and ROM space saved (or wasted) for various programming techniques.

Link to comment
Share on other sites

It would be nice to have more cycle count subsections on the bB page.

 

It would also be nice to have a new section or subsection that lists the cycle count and ROM space saved (or wasted) for various programming techniques.

I wouldn't mind contributing to this. Should I start a new topic or just send you updates via PM?

Link to comment
Share on other sites

I'm not exactly sure what you mean by loops back and forth. Could you provide an example? I do agree with you on keeping the code simple when possible. Also, I'm not trying to say that the method you suggested is wrong or worse. I just thought it would be interesting to analyze them more in depth and figured why not share my findings.

 

In my game you will notice that the two special attack animations (down+action) loop one way, mirror, and then loop the other way (while activating a collision, timed at the blade),and then stop and reset to the primary frame. This is very easy to do with two controlled variables. I use several instances in the game where two variables are used in tandem to control various aspects of animation.

 

Of course what is best for a programmer is best in the end. To argue eccentricities of style could go on forever. I sought out to be able to use similar methods for all of my animation cycles so controlling the mirroring of the player (like for moving left), jumping, rolling, and attacking is much easier to time, adjust and to understand!

Link to comment
Share on other sites

 

In my game you will notice that the two special attack animations (down+action) loop one way, mirror, and then loop the other way (while activating a collision, timed at the blade),and then stop and reset to the primary frame. This is very easy to do with two controlled variables. I use several instances in the game where two variables are used in tandem to control various aspects of animation.

I assume one of those variables is to count through the sequence of frames. How is the second variable used?

Link to comment
Share on other sites

In the case of left and right movement I use variables that are assigned to the directions to control animations.

 

Like this..

 

characterleft

REFP0=8
if n>15 then n=1

character

if joy0right then m=m+1
if !joy0right then m=0
if joy0left then n=n+1
if !joy0left then n=0
if m>4 then player0x=player0x+1
if n>4 then player0x=player0x-1

player0color:
*colors
end

if m>1 || n>1 then player0:
*frame1
end

if m>5 || n>5 then player0:
*frame2
end

if m>10 || n>10 then player0:
*frame3
end
if n>1 then goto characterleft
if m>15 then m=0

This creates a mirrored image of the right facing sprite for left movement. Of course, up and down movement, attacks, and jumps are all to be squeezed in there as well. The 4 is the speed regulator and, when increased, slows the character movement. This is far simplified (it should goto somewhere to create the circuit, possibly to a background and where it came from will have first landed on character, not characterleft) but should explain how two variables can be used to move and mirror an animated character.

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

Ok, now I get what you're doing. m is multiplexed to hold if the current state is moving right and the sequence count. n is multiplexed to hold if the current state is moving left and the sequence count.

 

Since the sequence count never exceeds 16 it only requires 5 bits and each state indicator only requires a bit each. You could multiplex all 3 into just a single variable. I don't think it would really make the code much more difficult to read and you free up a variable each place you are doing this. So it could be worth checking out. I can throw together some example code if you're not sure what I'm suggesting.

 

Here's a few comments about your example that may be helpful.

 

Aliases can be used to give variables more meaningful names.

 

 

bB does support if else constructs.

 if joy0right then m=m+1 else m=0

;is equivalent to

 if joy0right then m=m+1
 if !joy0right then m=0

When a variable needs to be limited to a range of 0 <= var < 2^n it can be bitwise ANDed with (2^n)-1 to save a few cycles and make the cycle count constant.

 m = m & $0F

;is equivalent to

 if m>15 then m=0

This also makes it easier to multiplex the direction indicators into the same variable.

 ;Roll sequence count back to 0 without clearing direction flags (bits 7 and 6)
 m = m & $EF
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...