It is currently Sat Oct 21, 2017 7:54 pm

All times are UTC - 7 hours





Post new topic Reply to topic  [ 13 posts ] 
Author Message
PostPosted: Sun Jul 30, 2017 2:14 am 
Offline
User avatar

Joined: Fri Jul 21, 2017 4:38 am
Posts: 31
Hey folks,

So I have my ship shooting... sort of... but when I press and hold the button down the bullet resets to the ship position as it should but it stays there for as long as the button is held down...

I'm using the movement code from Nerdy Nights and it works great for my ship's movement but I'm not sure how I can detect the initial button press down rather than if it's being held down. Sorry if I'm not explaining this well but here's my code. I have another label elsewhere that handles the bullet's movement.

Code:
LatchController:
   LDA #$01
   STA $4016
   LDA #$00
   STA $4016       ; tell both the controllers to latch buttons

; A button
ReadA:
   LDA $4016          ; player 1 button A
   AND #%00000001     ; only look at bit 0
   BEQ ReadADone   ; branch to ReadADone if button is NOT pressed (0)
   LDX $0217       ; load ship sprite X position
   STX $021B       ; move bullet to ship sprite X position
   LDX $0214       ; load ship sprite y position
   DEX            ; Move up a few pixels to align with ship
   DEX
   DEX
   STX $0218       ; move bullet to ship sprite Y position
ReadADone:         ; handling this button is done


EDIT: I'll try throwing in another variable... maybe set a value when button is pressed and reset it when the bullet hits the wall or enemy. That way I can check it when the button is held and only reset the bullet when the values match. Man I miss bools. LOL


Top
 Profile  
 
PostPosted: Sun Jul 30, 2017 2:31 am 
Offline
User avatar

Joined: Mon Jan 03, 2005 10:36 am
Posts: 2963
Location: Tampere, Finland
You need to save the buttons state from the previous frame. Then simply compare: "if previous=0 AND current=1 => button has been pressed after previously being down".

Some related links:
viewtopic.php?f=2&t=14809&p=179274#p179274
viewtopic.php?f=10&t=12456&p=142434#p142434

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


Top
 Profile  
 
PostPosted: Sun Jul 30, 2017 3:30 am 
Offline
User avatar

Joined: Fri May 08, 2015 7:17 pm
Posts: 1784
Location: DIGDUG
In neslib, it does this, after polling for new buttons...
;gets the current buttons, first, then it...
sta <PAD_STATE,y ;stores it
tax ;temp store
eor <PAD_STATEP,y ;any bits same as last frame, flip
and <PAD_STATE ,y ;mask only new presses
sta <PAD_STATET,y ;this is only the new buttons
txa ;restore from temp
sta <PAD_STATEP,y ;save again for next frame

I would have done this differently, but the important part is the EOR/AND to get only button presses new to the frame.

_________________
nesdoug.com -- blog/tutorial on programming for the NES


Last edited by dougeff on Mon Jul 31, 2017 5:26 am, edited 2 times in total.

Top
 Profile  
 
PostPosted: Sun Jul 30, 2017 3:30 am 
Offline
User avatar

Joined: Fri Jul 21, 2017 4:38 am
Posts: 31
thefox wrote:
You need to save the buttons state from the previous frame. Then simply compare: "if previous=0 AND current=1 => button has been pressed after previously being down".

Some related links:
http://forums.nesdev.com/viewtopic.php? ... 74#p179274
http://forums.nesdev.com/viewtopic.php? ... 34#p142434


Awesome, thanks!


Top
 Profile  
 
PostPosted: Mon Jul 31, 2017 2:05 am 
Offline
User avatar

Joined: Fri Jul 21, 2017 4:38 am
Posts: 31
Nope still stuck... I cant work out how to check the state of the button on the last frame... I've found a few C examples and asm examples that are using defines but I have no idea what those defines are...

How do I go about this in NESASM3?

I know the bit I need to check but I'm not sure how to store it and check it on the next frame.

Any more help greatly appreciated :)

Edit: Oh I just saw your reply, Doug. I think I know what to do now :)

Edit again: Still stuck - I'm confused as to what PAD_STATE, PAD_STATET and PAD_STATEP are?


Top
 Profile  
 
PostPosted: Mon Jul 31, 2017 5:17 am 
Offline
User avatar

Joined: Fri May 08, 2015 7:17 pm
Posts: 1784
Location: DIGDUG
Well, those are specific to shiru's code (neslib). It might be easier just to skip that for now, since you're working from nerdy nights.

Typically, you would read all buttons, and store them in a RAM address, for later retrieval.

I wrote about that here...
viewtopic.php?f=10&t=15684&p=191556
...near the bottom of the page.

There's also example code on the wiki...
http://wiki.nesdev.com/w/index.php/Controller_Reading

A simple way to store the last frame, is to copy the button presses to a second RAM address, just before reading the buttons again. Something like...

LDA controller1
STA controller1_last_frame
LDA controller2
STA controller2_last_frame
JSR read_controller

where these labels are all RAM locations.

_________________
nesdoug.com -- blog/tutorial on programming for the NES


Top
 Profile  
 
PostPosted: Mon Jul 31, 2017 12:00 pm 
Offline
User avatar

Joined: Fri Jul 21, 2017 4:38 am
Posts: 31
Great, I was on the right track. Will have a go tonight after work. Thanks again for your help!


Top
 Profile  
 
PostPosted: Fri Aug 04, 2017 7:07 pm 
Offline
User avatar

Joined: Fri Jul 21, 2017 4:38 am
Posts: 31
Okay, I've made some progress. Sorry, I'm pretty dumb when it comes to this stuff!

I have my shooting working but it works when I press as well as release the button now, so I get two bullets with every press and release. lol . Here's my code:

Code:
; A button
ReadA:
   LDA joypad                ; player 1 button A
   AND #%00000001           ; only look at bit 0 - clear all other bits
   CMP button_a_lastframe      ; compare a with button state of last frame
   BEQ ReadADone            ; branch to ReadADone if button is NOT pressed (0)
   LDX $0217                ; load ship sprite X position
   INX                     ; Offset a few pixels
   INX
   INX
   INX
   INX
   INX
   INX
   STX player_bullet_x          ; move bullet to ship sprite X position
   LDX $0214                ; load ship sprite y position
   DEX                     ; Move up a few pixels to align with ship
   DEX
   DEX
   STX player_bullet_y          ; save bullet y pos to ship sprite y position
   STA button_a_lastframe      ; Store button press state to use next frame
ReadADone:                  ; handling this button is done


Now I understand what's happening here... I think. Basically this code checks if the state of the button matches the state of the button last frame... problem is if the button is released then it will match, just like it does on initial press. What's an easy way to ignore button release? I have tried comparing with zero but nothing seems to work...

I did look over other examples but there were quite a few opcodes I just done't understand yet (I will though). I got the gist though, which is how I came up with this.

EDIT: I'm an idiot - BEQ means branch if equal to zero, doesn't it? I was thinking it meant if the two values compared were equal...
EDIT AGAIN: Nope - I was right first time. I'm getting zero confuded with zero flag, right? If the data and registers match, the zero flag is set. I think?


Top
 Profile  
 
PostPosted: Fri Aug 04, 2017 7:33 pm 
Offline

Joined: Sun Apr 13, 2008 11:12 am
Posts: 6293
Location: Seattle
mantanz wrote:
EDIT: I'm an idiot - BEQ means branch if equal to zero, doesn't it? I was thinking it meant if the two values compared were equal...
EDIT AGAIN: Nope - I was right first time. I'm getting zero confuded with zero flag, right? If the data and registers match, the zero flag is set. I think?
It means both!

Testing for equality is achieved by subtracting two numbers, setting the flags appropriately, and then throwing away the actual result. (The CMP, CPX, and CPY instructions). So you get the N, C, and V bits set appropriate, which is what the various Bxx instructions care about.


Top
 Profile  
 
PostPosted: Fri Aug 04, 2017 7:37 pm 
Offline
User avatar

Joined: Fri Jul 21, 2017 4:38 am
Posts: 31
lidnariq wrote:
mantanz wrote:
EDIT: I'm an idiot - BEQ means branch if equal to zero, doesn't it? I was thinking it meant if the two values compared were equal...
EDIT AGAIN: Nope - I was right first time. I'm getting zero confuded with zero flag, right? If the data and registers match, the zero flag is set. I think?
It means both!

Testing for equality is achieved by subtracting two numbers, setting the flags appropriately, and then throwing away the actual result. (The CMP, CPX, and CPY instructions). So you get the N, C, and V bits set appropriate, which is what the various Bxx instructions care about.

Aah. So I used BCS and now it only fires when I release the button. FML. LOL

EDIT: This is driving me nuts. Getting to the point I'd rather pay someone to fix it. LOL


Top
 Profile  
 
PostPosted: Fri Aug 04, 2017 9:13 pm 
Offline
User avatar

Joined: Fri Jul 21, 2017 4:38 am
Posts: 31
WOOHOO!

I got it working. Probably not the nuicest code and if anyone has any ideas how to streamline It'd be much appreciated but hell, it works!

Code:
; A button
ReadA:
   LDA joypad                ; player 1 button A
   AND #%00000001           ; only look at bit 0 - clear all other bits
   CMP joypad_lastframe      ; compare A with button state of last frame
   BEQ ReadADone            ; branch to ReadADone if button is NOT pressed (0)
   CMP #$0000
   BEQ ReadADone
   LDX $0217                ; load ship sprite X position
   INX                     ; Offset a few pixels
   INX
   INX
   INX
   INX
   INX
   INX
   STX player_bullet_x          ; move bullet to ship sprite X position
   LDX $0214                ; load ship sprite y position
   DEX                     ; Move up a few pixels to align with ship
   DEX
   DEX
   STX player_bullet_y          ; save bullet y pos to ship sprite y position
   ;STA joypad_lastframe
ReadADone:                  ; handling this button is done
   STA joypad_lastframe      ; S
tore button press state to use next frame


Top
 Profile  
 
PostPosted: Fri Aug 04, 2017 10:07 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10066
Location: Rio de Janeiro - Brazil
Since there may be many actions triggered by buttons being pressed, as well as actions triggered by buttons being held down, the common thing to do is to dedicate one variable for button states in each of those situations, so you can check them as many times as necessary during the frame, as opposed to doing comparisons against the previous state on a case-by-case basis. This is a simpler approach:

Code:
  lda joypad_down
  sta joypad_previous ;remember the old joypad state
  jsr ReadJoypad ;update joypad_down
  lda joypad_previous ;get the old joypad state
  eor #$ff ;invert all the bits, so that pressed buttons = 0
  and joypad_down ;turn any buttons that were already pressed into 0s
  sta joypad_pressed ;whatever buttons remain as 1s are new

Now you can trigger actions based either on joypad_down (e.g. walking) or joypad_pressed (e.g. shooting), depending on whether you want continuous reactions or not. For shooting you could do:

Code:
  lda joypad_pressed
  and #JOYPAD_A
  beq FiringDone
  ;(fire a shot here)
FiringDone:

No need for comparing button states here, since you already have a variable indicating all buttons that weren't pressed last frame but are pressed now.


Top
 Profile  
 
PostPosted: Sat Aug 05, 2017 12:29 am 
Offline
User avatar

Joined: Fri Jul 21, 2017 4:38 am
Posts: 31
Wow thanks! That helps heaps. I was wondering how to inverse the bits too. Cheers :)


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 13 posts ] 

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