New Project

A place where you can keep others updated about your NES-related projects through screenshots, videos or information in general.

Moderator: Moderators

User avatar
tokumaru
Posts: 11745
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Post by tokumaru » Sun Jun 19, 2011 12:50 pm

I don't think this is the best way to control the shooting though. The "shooting" variable will be set to 1 when the player presses A, but since he will release it soon after, "shooting" will become 0. According to the logic you posted before that would stop the bullet.

I think your frame logic should be more like this:

Code: Select all

IF A IS PRESSED AND THERE ARE FREE BULLETS
	RESET THE NEXT FREE BULLET TO THE PLAYER'S POSITION
	ACTIVATE THAT BULLET
END IF

FOR EACH ACTIVE BULLET
	MOVE BULLET UP
	IF BULLET COLLIDED WITH ENEMY
		KILL ENEMY
		DEACTIVATE BULLET
	END IF
NEXT BULLET
EDIT: Also, be sure to read this post and the ones after it, because they explain how to avoid repeated button detection. If you don't do what's explained in that thread, whenever someone presses "A" at least 5 or so bullets will be shot at once. Ideally, you will only fire bullets when the fire button transitions from not pressed to pressed, and those posts explain how to detect that transition.

dsv101
Posts: 36
Joined: Fri Jun 17, 2011 5:16 am
Location: United States
Contact:

Post by dsv101 » Sun Jun 19, 2011 2:42 pm

I dont know why, i just cant get this to work, ill figure it out though, hopefully :)

And i already know how to avoid joypad issues such as multiple frame detection and such
~Yeah, I Said That

User avatar
qbradq
Posts: 951
Joined: Wed Oct 15, 2008 11:50 am

Post by qbradq » Sun Jun 19, 2011 4:00 pm

The if statement thing you were asking about goes like this:

Code: Select all

    lda shooting
    cmp #1
    bne skip_shooting_down
    lda #0
    sta shooting
skip_shooting_down:
For an if-then-else, you would do it more like this:

Code: Select all

    lda shooting
    cmp #1
    bne else_clause
    ; DO STUFF
    jmp end_else
else_clause:
    ; DO OTHER STUFF
end_else:

dsv101
Posts: 36
Joined: Fri Jun 17, 2011 5:16 am
Location: United States
Contact:

Post by dsv101 » Sun Jun 19, 2011 7:16 pm

ill try this in a few days, im busy for now

but thanks :)
~Yeah, I Said That

dsv101
Posts: 36
Joined: Fri Jun 17, 2011 5:16 am
Location: United States
Contact:

Post by dsv101 » Sat Jun 25, 2011 11:53 am

Well, i've been pretty busy lately but recently, like 10 minutes ago, i sat down to work on this. I am starting to understand variables pretty well now, and how how they work in 6502 ASM. I decided to go with the .rsset and .rs method because it seems to be the best to use. This is what i cam up with for my problem (this will most likely be changed as the shooting system will be more efficient, in fact there isnt even one yet :) ):

Code: Select all

ReadA:
  LDA $4016
  AND #%00000001
  BEQ ReadADone

  LDA #$01
  STA shooting

  LDA #$00
  CMP shooting
  BEQ DontShoot

  LDA #$01
  CMP shooting
  BEQ Shoot

DontShoot:
  LDA #$FE
  STA $0204

Shoot:
  LDA #$80
  STA $0204

ReadADone:
this just stores a bullet off screen when a is not pressed, then when it is it moves to the middle of the screen. Next i will set up a shooting system.

3gengames
Formerly 65024U
Posts: 2276
Joined: Sat Mar 27, 2010 12:57 pm

Post by 3gengames » Sat Jun 25, 2011 12:04 pm

Make a controller reading routine that stores button states in a variable. I think tutorials and notes should be put up somewhere, as it seems nobody new to programming uses them at all. They just hardwire it into the engine. You reading GBAGuys or whoevers tutorials? Heh, but I guess it works. :)

dsv101
Posts: 36
Joined: Fri Jun 17, 2011 5:16 am
Location: United States
Contact:

Post by dsv101 » Sat Jun 25, 2011 12:16 pm

I used nerdy nights to get started, i also have many txt files and stuff i read. I like this way of reading a controller, but hey, knowing another way wont hurt :D
~Yeah, I Said That

3gengames
Formerly 65024U
Posts: 2276
Joined: Sat Mar 27, 2010 12:57 pm

Post by 3gengames » Sat Jun 25, 2011 12:22 pm

dsv101 wrote:I used nerdy nights to get started, i also have many txt files and stuff i read. I like this way of reading a controller, but hey, knowing another way wont hurt :D
This won't translate well to any game of size though, I'd suggest you do a JSR to a controller reading routine and then just read the button states and edit it there. There's no game to my knowledge that does hard coding of it like that, it's a doomed way to write it. Heh. :P

dsv101
Posts: 36
Joined: Fri Jun 17, 2011 5:16 am
Location: United States
Contact:

Post by dsv101 » Sat Jun 25, 2011 12:28 pm

lol, for now, this, later that :)
~Yeah, I Said That

3gengames
Formerly 65024U
Posts: 2276
Joined: Sat Mar 27, 2010 12:57 pm

Post by 3gengames » Sat Jun 25, 2011 12:55 pm

I'm sure all other decent programmers will advise against that.

User avatar
tokumaru
Posts: 11745
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Post by tokumaru » Sat Jun 25, 2011 4:06 pm

The only reason beginners find this weird method of controller reading easy is because some famous beginner tutorial uses it, but in reality it makes no sense at all to use that.

The simplest and most common way to read controller is to shift the states of all buttons into a variable and check that variable for the rest of the frame. There are 8 buttons, there are 8 bits in a byte, the most logical thing to do is use a bit to indicate the state of each button.

Also, it's good practice to separate the game logic from the hardware interactions. Say that for some reason you decide to convert your game to another platform that uses a 6502. As your code is now, you'll have to scan through all of the code looking for interactions with the $4016 register and change each one, because there will be a lot of them. If instead you made a separate subroutine whose only purpose was to read $4016 and put the button states in a byte, that would be all you'd have to change, because your game logic would only need that byte, regardless of where its contents came from. Your game logic wouldn't be tied to the hardware anymore, it's just common sense.

The same goes for video and audio. You must have a set of routines to deal with the PPU and the APU, but they should be as separated from the game logic as possible. For example, if your game uses missiles, the code that moves the missiles shouldn't be the same code that configures the OAM to display the missiles' sprites... The missile code should call a routine that draws sprites based on a set of parameters (such as a pointer to the meta-sprite definition), and this routine alone should mess with the OAM.

This is how professional games work. Even in AS3 (which you mentioned you know) you should work like this. If you program everything carelessly just to get results on the screen ASAP you'll end up with unmaintainable code, and this is one of the big reasons people give up on projects.

3gengames
Formerly 65024U
Posts: 2276
Joined: Sat Mar 27, 2010 12:57 pm

Post by 3gengames » Sun Jun 26, 2011 1:45 am

Here you go, controller reading routine: (I feel like a type this a lot.)

Code: Select all

[Put this in RAM somewhere]
ControllerButtonStates: .rs 0; Reserve a byte for the 8 button state bits from $4016.

LDX #$01
STX $4016
DEX
STX $4016
LDX #$08
ControllerReadUpdateLoop:
LDA $4016 ;Get controller button.
LSR A ;Put into the CARRY bit.
ROL ControllerButtonStates ;Update the button state. Once done 8 times, the value will be updated completely.
DEX ;X=X-1
BNE ControllerReadUpdateLoop ;Make it loop 8 times. If not done, get more button states.
RTS ;Done, ControllerButtonStates now holds all button states.
And now, you have a controller reading program for every game that uses just the brick controller. All you have to do is a JSR and you read the buttons you need them. What happens when you have to read and see if left+right are pressed? With this, instead of doing the right 4016 read, another 4016 read, a 4016 reset then shift back to where you were, it's rediculous. With this, you can check multiple states easily and you're not hoping back and forth on 4016, which you'll run into later following that way.
Last edited by 3gengames on Sun Jun 26, 2011 2:13 am, edited 1 time in total.

User avatar
tokumaru
Posts: 11745
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Post by tokumaru » Sun Jun 26, 2011 2:03 am

If you make a controller reading routine like the one 3gengames posted, to check a button you just have to do something like this:

Code: Select all

	LDA ControllerButtonStates ;get the button states
	AND #%00010000 ;check the 5th bit (don't remember which button this is, sorry!)
	BEQ NotPressed ;skip if the button is not pressed

	;THE BUTTON IS PRESSED! DO SOMETHING HERE!

NotPressed:
Much simpler than reading $4016 a million times per frame, don't you think?

dsv101
Posts: 36
Joined: Fri Jun 17, 2011 5:16 am
Location: United States
Contact:

Post by dsv101 » Sun Jun 26, 2011 2:07 pm

Guys Guys Guys, i said id do that later, by later i meant not right then, not as in i don't care ill keep it my way for now.

Anyway, thanks for the information and the example code :)
~Yeah, I Said That

User avatar
tokumaru
Posts: 11745
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Post by tokumaru » Sun Jun 26, 2011 3:30 pm

We're just trying to keep you from creating bad habits. What you currently have is pretty bad, and even in a tech demo will probably get out of hand soon. "Do it right from the start" is the advice we're giving you.

If you take a minute (literally) to carefully read what we told you (instead of just ignoring it or saving it for later), I seriously doubt you'll fail to see the advantages of doing it the proper way.

Post Reply