Originally posted by: brilliancenp
I have run into an issue and have an idea of how to deal with it but want to find out how other devs have tackled it. I have the need to capture an input string to perform a special player move. Think of it like throwing a fireball in street fighter 2 with ryu or ken. It isn't that many commands, I just want to do a double direction button push left or right.
I had the idea to record the previous button presses and then have a timer that the double push needs to be pressed within that time. Is this on the correct track? How would you guys go about accomplishing this?
I'd probably use my current button history routine in a certain way. Here's the routine:
;****************************************************************
;Deserializes the controller into a buffer.
;output: controller_buffer
;****************************************************************
.proc read_controller
lda #$01
sta CONTROLLER
lda #$00
sta CONTROLLER
lda CONTROLLER
ror
rol controller_buffer+buttons::_a
lda CONTROLLER
ror
rol controller_buffer+buttons::_b
lda CONTROLLER
ror
rol controller_buffer+buttons::_select
lda CONTROLLER
ror
rol controller_buffer+buttons::_start
lda CONTROLLER
ror
rol controller_buffer+buttons::_up
lda CONTROLLER
ror
rol controller_buffer+buttons::_down
lda CONTROLLER
ror
rol controller_buffer+buttons::_left
lda CONTROLLER
ror
rol controller_buffer+buttons::_right
rts
.endproc
What it does is record the last 8 states of every button in each byte of controller_buffer (which has reserved 8 bytes, one byte for each button). So, if someone JUST pressed a button, you can do this:
lda controller_buffer+buttons::_a
and #%00000011 ;only care about the current and previous state
cmp #%00000001 ;since we're now only looking at the most recent two bits, if the last bit was 0, and the current bit was 1, we now know the user JUST pressed the button.
If I wanted to detect a double press, I might double up the technique and record a history of actual detected presses, with another buffer like this:
.proc record_a_presses
;TODO: Add code to make recorded presses expire after a certain amount of time by
;rotating a 0 into button_a_pressed_buffer every few frames. this timer would get
;reset any time an actual press has been recorded, too.
lda controller_buffer+buttons::_a
and #%00000011 ;only care about the current and previous state
cmp #%00000001 ;since we're now only looking at the most recent two bits, if the last bit was 0, and the current bit was 1, we now know the user JUST pressed the button.
beq button_not_just_pressed
;Store that button a was actually pressed into button_a_pressed_buffer
lda #1
ror
rol button_a_pressed_buffer
button_not_just_pressed:
rts
.endproc
....I'd call that record_a_presses routine over and over again on each frame (as well as the controller read routine above), and to detect a double tap I would do this:
lda button_a_pressed_buffer
and #%00000111 ;examine last three states of whether button a was pressed
cmp #%00000011 ;this would mean two presses in a row (ONLY) were recorded
bne double_tap_not_detected
;Do your double tap action here
double_tap_not_detected:
...This might not be quite what you want either, as it may not take timing into consideration. There are other ways you could do it, but I'm fond of the bit history method, as it comes in handy for handling other types of transitions, not just button presses.
*edit* I'm thinking about timing, and you could make the button_a_pressed_buffer expire by rotating an unpressed state into it every few frames or something. Currently it'll detect the last two button presses no matter how much time passes.