News:

Building a 3D Ray Tracer  By stevmjon

Main Menu

Sprite Animation + Reference Arrays

Started by Tracy, January 27, 2006, 10:41:53 PM

Previous topic - Next topic

Tracy

okay, can anyone tell me why this function doesn't work properly? I THOUGHT it was pretty straightforward, but it seems to only set the pointer array once, and leaves it alone on other passes. I know that the player(p).action string is getting updated, because I print it over my sprite and it works like a charm, so the issue isn't there. I can get my little guy to walk, but after that he's stuck walking and I don't understand why. (It IS animated walking, though... which is something, I guess.)

PlayBASIC Code: [Select]
Function AnimatePlayer(p)

If player(p).action="walk" then Setarray Anim(),Getarray(PLayerWalkAnim())
If player(p).action="stand" then Setarray Anim(),Getarray(PLayerStandAnim())
If player(p).action="fly" then Setarray Anim(),Getarray(PLayerFlyAnim())


If Timer()-player(p).animation_timer>85
player(p).Frame=player(p).frame+1
If player(p).frame>Anim(0) then player(p).Frame=1
Spriteimage player(p).Spr,Anim(player(p).frame)
player(p).animation_timer=timer()
Endif

Endfunction

; What I've found is that it'll update with the following:

If LeftKey() And player(player).busy=0

player(playeR).facingleft=1

If player(player).jump_status=0
Player(player).action$="fly"

EndIf

If player(Player).Xspeed# > -Player(Player).X_TopSpeed# And player(player).dash_status=0
player(Player).Xspeed#=PLayer(Player).Xspeed#-Player(Player).XAccel#
player_moved=1
EndIf

EndIf

; But not this one: (Which looks dang near identical to me, which is why I'm so blasted confused.)

If RightKey() And player(player).busy=0

Player(player).facingleft=0

If player(player).jump_status=0
Player(player).action$="Walk"
EndIf

If player(Player).Xspeed# < Player(Player).X_TopSpeed# And player(player).dash_status=0
player(Player).Xspeed#=PLayer(Player).Xspeed#+Player(Player).XAccel#
player_moved=1
EndIf

EndIf





Sorry to be inundating the forums with so many questions/problems, but I'm not a programmer by trade and all of this is fairly new to me. Thanks in advance.

Edit: I've found a way around the problem: I simply put the SetArray command directly into the "If LeftKey/RightKey..." If statements and it works great. I'd still rather not do it that way, though, because I'd rather have the SetArray portion of things built into the AnimatePlayer function. Again, if anyone sees the problem please point it out. Thanks.

Edit2: I've discovered that my string value isn't passing into my function, though it's clearly defined in the Player type as a player variable. I have functionally solved this particular problem, but I still don't see why the above solution didn't work. Anyone?

Ian Price

#1
Without going right through every line I notice that in your function you use Player(P), but in your code you use Player(player) - are you giving the variable "player" a value? I personally wouldn't use variable names that are similar to function names. Are you calling the "player()" function every frame?

This code also has several spelling differences - you declare "walk" and "Walk", "player" and "Player" and "PLayer" etc. - I don't know if PlayBASIC is case sensitive for these or not.

Also, using the [KODE][/KODE] - replace "KODE" with "CODE" tags makes your code a lot easier to read.

Plus by not including the whole movement function, we can't see if the problem lies elsewhere within that function.
I came. I saw. I played some Nintendo.

kevin

Yes, it's hard to work out whats going on with fragments, but i think Ian has hit the nail on the head with the case of the strings your using for each animation mode.

When you compare strings,  they have to match perfectly (the case matter) in order to get a hit.  

ie.


a$="Bill"
if a$="bill"  then print "yep matched the first one"
if a$="bIll"  then print "yep matched the second one"
if a$="Bill"  then print "yep matched the third one"
sync
waitkey


I'd prolly use constants over strings anyway.  Then there's no case issues, plus integers/float compares are quicker than string compares

ie.

Constant Anim_Walking =1
Constant Anim_Running =2
Constant Anim_Dead =3


 
Also, rather than using a handfull of IF/THEN statements to determine which animation array you with you use you could use a SELECT/CASE structure.  



 Select Player(ThisPlayer).AnimMode
        case  Anim_Anim_Walking
           setarray anim(),getarray(walking_animation())

        case  Anim_Anim_Running
           setarray anim(),getarray(Running_animation())

        case  Anim_Anim_Dead
           setarray anim(),getarray(Dead_animation())
 Endselect


Tracy

#3
Thanks guys. The fact that PB doesn't mind alternate capitolizations when calling a non-string variable, but DOES notice the differences in strings (which makes perfect sense now that it's been pointed out to me) was what was causing the problem.

And sorry for not including the entire code- I'm pushing 2000 lines at this point, which means I'm starting to hit the bug-thicket because it's becoming complex enough that I can no longer easily trace the problem. (So I'm becoming frustrated and asking for help more often, which makes it a lot easier to deal with. This forum hasn't failed me yet, so I'm trying not to wear out my welcome. Seriously, this is great.)

Double thanks for your near never-ending patience with the new guy on the block. Enjoy your weekend, both of you.  B)

kevin

#4
No worries..  


 Since you used the reference arrays (prolly the the first one to that :) ) here's a few tidbits for the other reading this thread..


 A reference array allow us to reference the contents of other arrays, without have to pass them (into functions).

Simple Example (not a lot of use like this)

PlayBASIC Code: [Select]
; Dimension the Array Table1(). 
Dim Table1(10)

; create a redirectable array Stub called Anim()
MakeArray Anim()

; Point our redirection array Anim() at Table1().
SetArray Anim(),getArray(Table1())

; Amim() now acts as Table1()
For lp=0 to getArrayElements(Anim(),1)
Anim(lp)=1000+lp
next

; To prove that lets view the contents of Table1()
For lp=0 to 10
print Table1(lp)
next

sync
waitkey






kevin

#5
Mutli array example


PlayBASIC Code: [Select]
; Dimension the some arrays(). 
Dim Table1(5)
Dim Table2(10)
Dim Table3(15)
Dim Table4(20)


; create a redirectable array Stub called Anim()
MakeArray Anim()

Counter=100
For Array=0 to 3
; Point our redirection array Anim() at one of the table arrays()
; as long as their dimensioned sequentially (as above) you
; can simply set through them
SetArray Anim(),GetArray(Table1())+ Array

; Amim() now acts as one of Table() arrays
For lp=1 to getArrayElements(Anim(),1)
Anim(lp)=Counter
inc counter
next

next


; Now run through and view the contents of all of them
For Array=0 to 3
SetArray Anim(),GetArray(Table1())+ Array
t$=""
; Amim() now acts as one of Table() arrays
For lp=1 to getArrayElements(Anim(),1)
t$=t$+str$(anim(lp))+","
next
print t$
next


sync
waitkey







kevin

#6
This version uses to marker arrays, so you can dynamically access any arrays between them


PlayBASIC Code: [Select]
; Dim A starting array purely as marker
Dim StartTableArrays(0)

; Dimension the some arrays().
Dim Table1(5)
Dim Table2(10)
Dim Table3(15)
Dim Table4(20)
Dim Bill(25)
Dim JAck(20)
Dim Jim(15)
Dim Bob(10)
Dim HelloWorld(5)


; Dim an Array as the end market of arrays.
Dim EndTableArrays(0)



; create a redirectable array Stub called Anim()
MakeArray Anim()

Counter=100

; Run through whatever arrays are defined between out start end end marker
; arrays
For Array=GetArray(StartTableArrays())+1 to GetArray(EndTableArrays())-1
SetArray Anim(),Array
; Amim() now acts as one of Table() arrays
For lp=1 to getArrayElements(Anim(),1)
Anim(lp)=Counter
inc counter
next
next


; Now run through and view the contents of all of them
For Array=GetArray(StartTableArrays())+1 to GetArray(EndTableArrays())-1
SetArray Anim(),array
t$=""
; Amim() now acts as one of Table() arrays
For lp=1 to getArrayElements(Anim(),1)
t$=t$+str$(anim(lp))+","
next
print t$
next


sync
waitkey





kevin

#7
  What this allows us to do is if you define our animations in a linear fashion, we can simply use a reference array to selectively point at any animation array()  we like.  


PlayBASIC Code: [Select]
; Dimension an array, purely as a marker from which you can index the following (they must be in order) animation arrays
Dim AnimationBaseArray(0)

; Dimension some animation Arrays() + make some constants for each animation mode/array.
Dim Anim_Standing(5) ;
Dim Anim_Walking(10)
Dim Anim_Dead(20)
Dim Anim_Sneeze(25)


; Define some sequential constants that we can use to represent our animations
; in our code (these have to match the order the arrays are dimmned above
acset =0
Constant Anim_StartOfAnims =ac(1)
Constant Anim_Standing =ac(1)
Constant Anim_Walking =ac(1)
Constant Anim_Dead =ac(1)
Constant Anim_Sneeze =ac(1)
Constant Anim_EndOFAnims =ac(1)


; create a redirectable array Stub called Anim()
; this is used as to access the animation arrays above, via indirection
MakeArray Anim()

Counter=100

; Run through and fill them with values
For Array=Anim_StartOFAnims+1 to Anim_EndOFAnims-1
SetArray Anim(),Getarray(ANimationBaseArray())+Array
For lp=1 to getArrayElements(Anim(),1)
Anim(lp)=Counter
inc counter
next
next


CurrentAnim=Anim_Standing

Do
cls 0

; Display Message
Print "Curent Animation:"+STR$(CurrentAnim)


; Now run through and view the contents of all of them
SetArray Anim(),Getarray(ANimationBaseArray())+CurrentAnim
t$=""
For lp=1 to getArrayElements(Anim(),1)
t$=t$+str$(anim(lp))+","
next
print t$


if Spacekey()=true
Inc CurrentAnim
; if the current anim index has hit the end of the define number
; of animations, then reset it
if CurrentAnim=Anim_EndOFAnims
CurrentAnim=Anim_StartOFAnims+1
endif
Flushkeys
endif

if Scancode()=0 then KeyPressed=False

Sync
loop