Page 2 of 2

Re: DELAYS??

Posted: Fri Jul 07, 2006 5:21 am
by Memblers
nineTENdo wrote: Do you know of a simple algorithm to just add X of a sprite movement?
This isn't the simplest (simplest would be just to INC or ADC to a byte in RAM), but here is a good way to do it that gives accuracy down to 1/256th of a pixel for smooth movement at any speed.

Code: Select all


x_position_lo = $00   ; anywhere in RAM
x_position_hi = $203 ; in your sprite-RAM buffer
                               ; $203 is sprite #0 just for example

movement_speed = $011C ; this is a little bit faster than 1 pixel per frame
                                       ; $0100 would be one pixel/frame exactly.

 lda x_position_lo
 clc
 adc #<movement_speed
 sta x_position_lo
 lda x_position_hi
 adc #>movement_speed
 sta x_position_hi
In my NMI routines I stick to only handling VRAM, Sprite-RAM DMA, and also music. Because even if the game engine slows down, you don't want the music to slow down.

Re: DELAYS??

Posted: Fri Jul 07, 2006 5:40 am
by tepples
Memblers wrote:This isn't the simplest (simplest would be just to INC or ADC to a byte in RAM), but here is a good way to do it that gives accuracy down to 1/256th of a pixel for smooth movement at any speed.
nineTENdo: If you're interested in the technique Memblers describes, it's called fixed-point arithmetic.

Re: DELAYS??

Posted: Fri Jul 07, 2006 12:22 pm
by nineTENdo
Memblers wrote:

Code: Select all


movement_speed = $011C ; this is a little bit faster than 1 pixel per frame
                                       ; $0100 would be one pixel/frame exactly.

 [/quote]

*LIGHTBULB*

So this a good way to adjust speed of sprite movements huh?

Re: DELAYS??

Posted: Fri Jul 07, 2006 1:24 pm
by Memblers
nineTENdo wrote:
Memblers wrote:

Code: Select all


movement_speed = $011C ; this is a little bit faster than 1 pixel per frame
                                       ; $0100 would be one pixel/frame exactly.

 [/quote]

*LIGHTBULB*

So this a good way to adjust speed of sprite movements huh?[/quote]

Yep, it's just great (wish I had known of it a long time ago).  That example is just hard-coded to one speed though, another possibility is to change that movement_speed to be a table and use an index register during the ADCs to select from some pre-defined speeds.  That's what I did in Munchie Attack.

Re: DELAYS??

Posted: Fri Jul 07, 2006 2:21 pm
by tokumaru
Memblers wrote:another possibility is to change that movement_speed to be a table and use an index register during the ADCs to select from some pre-defined speeds.
Or you could make "speed" a variable and perform some math on it. Often when I implement movement, the keys act on the speed variable (as opposed to the player's position). The right key would increase the value of "speed" (until a max positive value) and the right key would decrease it (until a min negative value). When neither is pressed, it's progressively forced toward 0. And "speed" is always (every frame) added to the player's coordinates.

This adds a nice acceleration and inertia effect to the game. I often have acceleration on the Y axis too, wich means that all you have to do to jump is place a way high value on "speedY". No floor under the player causes "speedY" to increase (until a max positive value), simulating gravity (wich is what brings you down after a jump). If you find good values for the step you use to increment/decrement and the max/min values, it can look and feel very nice.

Posted: Fri Jul 07, 2006 2:37 pm
by Bregalad
I like working with 8 bit speed variable, the high 4 bits being the pixel increment per frame and the 4 low bits represents the 1/16 internal counter increment.
You'd never want to move a sprite slower than 1/16 pixel a frame, and never faster than 8+7/16 pixels a frame, so this enable you to work with easy 8-bit speeds, $10 being the standard 1 pixel per frame speed.

Posted: Fri Jul 07, 2006 2:45 pm
by tepples
Bregalad wrote:You'd never want to move a sprite slower than 1/16 pixel a frame
But you may want to accelerate a sprite slower than 1/16 pixel per frame per frame. For instance, at 16 pixels = 1 meter and 60.0988 frames = 1 second, standard Earth gravity is 0.0434 pixels per frame per frame, or 0.695 of your units.

Posted: Fri Jul 07, 2006 7:02 pm
by tokumaru
Bregalad wrote:I like working with 8 bit speed variable, the high 4 bits being the pixel increment per frame and the 4 low bits represents the 1/16 internal counter increment.
I like it this way too.
You'd never want to move a sprite slower than 1/16 pixel a frame, and never faster than 8+7/16 pixels a frame
Then again, there is Sonic... but that's another story!

Also, i usually don't worry about real physics, I set the values to what looks and feels best for a game. Real physics aren't fun in a platformer. Don't you hate games where you can't change your direction in the middle of a jump?

Posted: Sat Jul 08, 2006 12:20 am
by Bregalad
Also, i usually don't worry about real physics, I set the values to what looks and feels best for a game. Real physics aren't fun in a platformer. Don't you hate games where you can't change your direction in the middle of a jump?
So true. I like projectiles that goes at constant speed anyways. And if you can play Castlevania for a while without be frustrated by its horrible jump control, I don't know how you do.
Anyway this all depend how you plan to code your game engine.
Tokumaru : You're speaking of signed speed variables. In my game engine I'm writing for my action-adventure game, I only have speed on projectiles, but monsters are animated by their own AI so they can move at constant or variable speed if they have a programm to move them their way, and the player always move at the constant speed of 1.5 pixels per frame (assuming it moves). I don't use signed variables for speed, but rather another direction variable. So it is easier for a monster to create a new projectile with the same speed, but another direction. The direction byte also serves to determine wich sprite is shown on player/monster (and possibly projectiles too if they're not bland round). I didn't say it is the best way, but it is like I did, and my game engine isn't finished yet.

Inner Loops

Posted: Sun Jul 30, 2006 2:57 am
by nineTENdo
Hello Again,
Ive been working on a number demo that toggles through tiles each set with 1,2,3,etc. When i run it in my NMI i can see that the numbers are changing but its going way to fast. Can i use inner loops to slow it down? So far ive been using outer loops but i doesnt seem to be working. Any ideas?
Heres the code:

Code: Select all

nmi
	pha
	txa
	pha
	tya
	pha

	LDA #$50
	STA X_POS
	STA Y_POS



TOGGLE	
	LDA TILE,X
	STA $0701
	INX
	INX
	INX

	LDA #$7
	STA $4014
	
	BNE TOGGLE           <--Does this really need to be there?
	

END		
	
	
	pla
	tay
	pla
	tax
	pla
	
	rti

irq:
	rti

TILE
	.DB 02,03,04,05,06,07,08,09
Anything to spify up what im doing here will help.

Thanks in Advance,

EL

Posted: Sun Jul 30, 2006 6:41 am
by Disch
I didn't want to answer this directly -- rather I wanted to try and point you in the right direction, so that you can see what's wrong and try to fix it on your own.

Your 'TOGGLE' section is very strange. Ask yourself the following questions:

1) What purpose do those 'INX' lines serve? Are they really doing what you expect them to?
2) When do you want that BNE to branch? and when do you want it NOT to branch? Is it really branching how you'd expect?
3) How are you keeping track of which number you are currently displaying? And how do you know which number to display next?
4) How many times is this code actually writing to the sprite DMA register ($4014) per frame? How many times do you want it to write to sprite DMA?

Once you answer these questions, you will be on your way to solving this problem.

In times like these, it's often useful to create a trace log and watch what the ROM is doing. Run your ROM in FCEUXD, go to Tools | Trace Logger, and trace a few frames... then look to see what the code is doing. If it isn't behaving like you expect it to, try and figure out why... then you'll find the problem in your code.

Posted: Sat Aug 12, 2006 9:48 pm
by nineTENdo
Disch wrote:
1) What purpose do those 'INX' lines serve? Are they really doing what you expect them to?
2) When do you want that BNE to branch? and when do you want it NOT to branch? Is it really branching how you'd expect?
3) How are you keeping track of which number you are currently displaying? And how do you know which number to display next?
4) How many times is this code actually writing to the sprite DMA register ($4014) per frame? How many times do you want it to write to sprite DMA?
Sorry for the late reply. Been busy.
Well #1 ive come to find out i really dont need them just one INX will do. i used them becasue i though it would increment the $0701 register to $0704 for the tile number but i figured i was only using one sprite and just switching the tile number. but in any case that wouldnt do that anyway.

#2 i have to put the branch there becasue my nmni wont work if its not there. i would have thought that the NMI would still run it anyways, but it dosent.

#3 i know what number to display next casue im just changing tile numbers and i can see the numbers changing only really really fast.

#4 i figured it would write to sprite DMA after each increment to update the tile number.

What i want is to run the code so each tile is updated slowly casue it to look like the numbers where changing. but i can seem to get past the BNE part it seem you can run an inner branch for time delays with out letting the BNE MOVE1 keep incrementing. Do you know what i mean??? im thinking i might have to use some varibles. What do you think??? Any tips?

Posted: Sun Aug 13, 2006 6:55 am
by Disch
Did you try making a tracelog with FCEUXD and see what the code is doing?

Well #1 ive come to find out i really dont need them just one INX will do.
Well what I was getting at... was it is really doing what you thought? The only time you're using X is in your tile lookup "LDA TILE,X" -- and even then you're never setting X to any initial value, and you're not preventing it from being greater than 8 -- so most of the time you're probably reading garbage.
#2 i have to put the branch there becasue my nmni wont work if its not there.
That's not what I meant. And in fact.. .the NMI probably IS working without it... you're just not doing something else right. Instead of plugging in random lines of code and seeing the result... you should really try to understand what each line does. You'll never solve a problem by guessing which lines you might have to insert -- the only way to solve the problem is to understand it.

'BNE' will branch if the Z flag is clear.... right? So what line of code above that BNE changes the Z flag? Does it set or clear the Z flag? When does it set it and when does it clear it?
#3 i know what number to display next casue im just changing tile numbers and i can see the numbers changing only really really fast.
Well I gather that's sort of what X is tracking -- but if you'll notice, you never set X to anything when you enter NMI. So the tile you draw is never specified.

What I was hinting at before was that you should be keeping a variable which is tracking the tile you want to draw. You should never keep long-term variables like that just in a register.. registers are just for work and quick temporary stuff. For something you want remembered between frames, you definately want to have a variable for it.
#4 i figured it would write to sprite DMA after each increment to update the tile number.
But how often is that? Does it make any sense to update sprite RAM more than once per frame? How many times per frame are you actually doing it?



You really should pick up a copy of FCEUXD... run your ROM in it and make a trace log so you can see what your ROM is actually doing. If it isn't exactly following what you expect it to, then you can ask yourself "why is it doing it this way", and you can examine the log to find the answer, and fix the problem in your code.

To be a little more direct with the main problem you're having (but without giving away the solution):

Your TOGGLE section is an infinite loop, the only time your program is escaping it is when ANOTHER NMI triggers (adding onto the previous NMI, and eventually overflowing your stack). Basically, it's just a really nasty infinite loop your program gets caught up in on the very first NMI.