It is currently Tue Jun 19, 2018 11:22 am

All times are UTC - 7 hours





Post new topic Reply to topic  [ 21 posts ]  Go to page Previous  1, 2
Author Message
PostPosted: Wed Feb 28, 2018 9:20 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10513
Location: Rio de Janeiro - Brazil
instantaphex wrote:
Will this have the same effect? Will it expand out into an array of the low bytes and high bytes?

This is just combining 2 separate functionalities of ca65: the .define command creates an identifier that will expand into the list of things every time you use it, while .lobytes and .hibytes will extract only the low or high bytes of the list of values you give them. So yeah, this will create two tables, one with only the low bytes and the other with only the high bytes.

Quote:
I've noticed some people using some "dot" type notation in their code, is this just by convention or is there some syntactic sugar for that type of thing in ca65?

Sounds like you're talking about scopes. Scopes encapsulate symbols so they're not visible to parent scopes, unless you use named scopes and access their children using "::". For example: jsr Video::UpdatePalette will call the subroutine "UpdatePalette" that was defined inside the "Video" scope. Scopes are useful for organization purposes, but also allow you to reuse labels (e.g. if each subroutine has its own scope, all of the can have a label called "Return").


Top
 Profile  
 
PostPosted: Wed Feb 28, 2018 10:04 pm 
Offline
User avatar

Joined: Sat Sep 27, 2014 10:10 pm
Posts: 30
Location: Houston, TX
tokumaru wrote:
instantaphex wrote:
Will this have the same effect? Will it expand out into an array of the low bytes and high bytes?

This is just combining 2 separate functionalities of ca65: the .define command creates an identifier that will expand into the list of things every time you use it, while .lobytes and .hibytes will extract only the low or high bytes of the list of values you give them. So yeah, this will create two tables, one with only the low bytes and the other with only the high bytes.

Quote:
I've noticed some people using some "dot" type notation in their code, is this just by convention or is there some syntactic sugar for that type of thing in ca65?

Sounds like you're talking about scopes. Scopes encapsulate symbols so they're not visible to parent scopes, unless you use named scopes and access their children using "::". For example: jsr Video::UpdatePalette will call the subroutine "UpdatePalette" that was defined inside the "Video" scope. Scopes are useful for organization purposes, but also allow you to reuse labels (e.g. if each subroutine has its own scope, all of the can have a label called "Return").


Ok that makes sense. As far as the scopes are concerned, that isn't quite what I was referring to. I was referring to seeing things like:

Code:
player.animations.walk


Top
 Profile  
 
PostPosted: Wed Feb 28, 2018 10:13 pm 
Offline
User avatar

Joined: Sat Sep 27, 2014 10:10 pm
Posts: 30
Location: Houston, TX
Kasumi wrote:
No problem, and it seems you're really getting it!

One other suggestion: You can maybe add the frame count as a parameter to your macro which would make it more fully generic, I think.


I had forgotten that I moved my frame count data outside of my sprite pointer array. You're right I need to pass it in. I've made a couple of updates now so that I can pass in a pointer to an animation and a pointer to a number of frames. This way I can transition between frames based on the state of the player.

Code:
.macro play_animation animation, num_frames, counter, sprite_ptr
    ; load sprite frame counter
   lda counter
    ; advance frame (initially $ff and rolls over to 0)
    clc
    adc #1
    ; if (current_frame == num frames) { reset() }
    ldx #0
    cmp (num_frames,x)
    bcc skip_reset
    lda #0
skip_reset:
    ; store frame + 1
    sta counter
    ; multiply a by 2 in order to get correct byte offset
    asl a
    ; transfer a to x for Absolute,X addressing mode
    tay
   ; set current sprite to current animation frame
   lda (animation), y
   sta sprite_ptr + 0
    iny
   lda (animation), y
   sta sprite_ptr + 1
.endmacro


It feels a little clunky to have to use:
Code:
ldx #0
cmp (num_frames,x)


but I didn't see another option.

Now I'm trying to figure out how to register button releases so I can transition in and out of walking and idle states. Right now I'm just storing a single frame of controller state. I assume I probably will want to store 2 frames and compare. If the previous frame's state shows that left has been pressed but the current frame's state shows that it's not pressed, then I can transition from the walking state back to the idle state. Hopefully that will work.


Top
 Profile  
 
PostPosted: Wed Feb 28, 2018 10:35 pm 
Offline

Joined: Tue Feb 07, 2017 2:03 am
Posts: 447
Quote:
player_walking_1:
.byte $00,$32,%00000000,$00
.byte $00,$33,%00000000,$08
.byte $08,$34,%00000000,$00
.byte $08,$35,%00000000,$08

player_walking_2:
.byte $00,$36,%00000000,$00
.byte $00,$37,%00000000,$08
.byte $08,$38,%00000000,$00
.byte $08,$39,%00000000,$08

etc...

player_walk_animation:
.byte $04 ; number of frames
.word player_walking_1, player_walking_2, player_walking_3, player_walking_4


This is getting more advanced so once you have worked out the above, the next step it to store the attributes as arrays.
So
Code:
Frame_X             .byte $00,$08,$00,$08,$00,$08,$00,$08
Frame_Tile          .byte $32,$33,$34,$35,$36,$37,$38,$39
Frame_Atrribute     .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000,%00000000,%00000000
Frame_Y             .byte $00,$00,$08,$08,$00,$00,$08,$08

Then you put Frame in X
Code:
lda Frame_X,x
sta Dest,y
lda Frame_Tile,x
sta Dest+1,y
lda Frame_Attribute,x
sta Dest+2,y
lda Frame_Y,x
sta Dest+3,y
tya
clc
adc #4 ; move to next sprite slot
tay
; while still frame left, get next frame index and loop


You then stack N animations in the main tables. Then your Walk animation either becomes a list of frames, or if you know you only want a range then you have
Start,End
So you keep a frame index in RAM, load it with Start, inc it each time until it hits End, then reset it to start.

Putting the data stripped in this way is a pain, but if you upgrade to Tass64 (which works on Mac Intel and PPC ) over CA65 you can start to do things like
Code:
My_Animations := (($00,$32,%00000000,$00),($00,$33,%00000000,$08),($08,$34,%00000000,$00),($08,$35,%00000000,$08),($00,$36,%00000000,$00)....)
PlayerWalkEnd = len(My_Animations)
You can add addition animations with
My_Animations ..= ( anims )

Then you do
Frame_X             .byte My_Animations[:0]
Frame_Tile          .byte My_Animations[:1]
Frame_Atrribute     .byte My_Animations[:2]
Frame_Y             .byte My_Animations[:3]

PlayerWalk .byte $04,$00,PlayerWalkEnd ; frames,start,end


Word to the wise.
Don't hard code tile numbers, it is going to cause your a lot of pain latter on when you need to move things, and you will need to move things ;) Also they are not very readable
Code:
kTileIndex .block
    PlayerHead .block
        L = $34
        R = $35
    .bend
    PlayerLegWalk
        f1 .block
            L = $36
            R = $37
    .bend
.bend

Yes its a lot more typing, but then in 3 months when you need to change an animation how much more sense does
Frame_Tile .byte $32,$33,PlayerHead.(L,R),PlayerLegWalk.f1.(L,R),$37,$38,$39 make?


Top
 Profile  
 
PostPosted: Thu Mar 01, 2018 11:05 am 
Offline
User avatar

Joined: Fri Nov 24, 2017 2:40 pm
Posts: 31
Oh Interesting. I didn't know about .lobytes/hibytes. That certainly makes striped arrays more usable.


Top
 Profile  
 
PostPosted: Sun Mar 11, 2018 1:05 am 
Offline
User avatar

Joined: Mon Jan 03, 2005 10:36 am
Posts: 3076
Location: Tampere, Finland
It's also possible to duplicate the .lobytes/.hibytes functionality by using macros. This is sometimes useful if you need to do more complicated transforms, or extract some auxiliary data such as the bank byte.
Code:
.macro transform v, func
    .repeat .tcount({v}), i
        func {.mid(i, 1, {v})}
    .endrepeat
.endmacro

.macro lobyte v
    .byte .lobyte(v)
.endmacro

.macro hibyte v
    .byte .hibyte(v)
.endmacro

.macro bank v
    .byte .lobyte(.bank(v))
.endmacro

Usage:
Code:
.define maps map_foo map_bar map_xyzzy
maps_lo: transform {maps}, lobyte
maps_hi: transform {maps}, hibyte
maps_bank: transform {maps}, bank

Note though, that since this operates on tokens you can't have more complex expressions within the .define list itself. This won't work: .define maps map_foo+123 map_bar*2. However, it would be possible to modify the transform macro to support that as well (delimit the parameters by ,), I just wanted to keep it simple.

_________________
Download STREEMERZ for NES from fauxgame.com! — Some other stuff I've done: fo.aspekt.fi


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 21 posts ]  Go to page Previous  1, 2

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 4 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group