SpriteCreationWithDyzen: Difference between revisions
No edit summary |
|||
Line 8: | Line 8: | ||
Also, it should be noted that this tutorial can also serve for sprites which are not created with Dyzen, though the focus is ultimately based on those. | Also, it should be noted that this tutorial can also serve for sprites which are not created with Dyzen, though the focus is ultimately based on those. | ||
== Creating a CFG/JSON with CFG Editor == | |||
== Sprite Structure == | == Sprite Structure == | ||
Revision as of 01:09, 27 March 2021
English | Português | Español | 日本語 |
The following tutorial will explain how to create sprites using Dyzen. This tutorial covers not just how to use the tool, but also general functions for the creation of regular, cluster, and extended sprites.
For this tutorial, it's assumed that the developer has previous knowledge of ASM like using basic commands, branching, and indexing. This tutorial is based more on how to construct the logic of a sprite.
Also, it should be noted that this tutorial can also serve for sprites which are not created with Dyzen, though the focus is ultimately based on those.
Creating a CFG/JSON with CFG Editor
Sprite Structure
A sprite is structured in the following manner:
-
Sprite Init: This is the routine which occurs when the sprite is spawned. In Pixi, this routine begins with the line:
print "INIT ",pc
And should end with an RTL.
-
Sprite Main: This routine is called in each Game Loop (SNES Frame) and is used for updating the sprite and its logic. In PIXI, this routine begins with the line:
print "MAIN ",pc
And should end with an RTL. Usually this routine would be like so:
print "MAIN ",pc PHB PHK PLB JSR SpriteCode PLB RTL
This calls a routine named SpriteCode which will have the real contents of this routine. This is performed to better organize the code. Also, the Program Bank is set so that the tables can be indexed with short absolute indexing ($XXXX,x o $XXXX,y), instead of using long indexing, optimizing the number of cycles the code uses.
-
SpriteCode: It basically contains the Main routine, as described above. This routine is called by others which will carry out the logic of the sprite. We will separate these routines into DynamicRoutine, GraphicRoutine, InteractionWithPlayer, InteractionWithSprites, StateMachine, AnimationRoutine, etc., depending on whatever the sprite requires. The basic structure of this routine is:
SpriteCode: .AlwaysExecutedZone JSR GraphicRoutine ;Calls the graphic routine and updates sprite graphics ;Here you can put code that will be excecuted each frame even if the sprite is locked LDA !SpriteStatus,x CMP #$08 ;if sprite dead return BNE Return LDA !LockAnimationFlag BNE Return ;if locked animation return. .ExecutedIfNotLocked %SubOffScreen() JSR InteractMarioSprite ;After this routine, if the sprite interact with mario, Carry is Set. ;Here you can write your sprite code routine ;This will be excecuted once per frame excepts when ;the animation is locked or when sprite status is not #$08 JSR AnimationRoutine ;Calls animation routine and decides the next frame to draw RTS Return: RTS
Here we can take note of 2 main zones (blocks of code):
- .AlwaysExecutedZone which encompasses the area from the beginning of the routine until the first check
LDA !SpriteStatus,x
. This zone always runs, even if the game is paused or the animations are stopped, normally we don't put a lot of code in this zone, except for graphics routines. - .ExecutedIfNotLocked encompasses the area after the check
LDA !LockAnimationFlag
. This zone runs when the animations aren't stopped, the game isn't paused, or the player is not in the death animation, etc. Also, it should be clarified that this sector is only executed if the !SpriteStatus,x has the value 8. This means that the sprite has the status "Normal Routine". This RAM address corresponds with the table$14C8
. It should be noted that the check of!SpriteStatus,x
can be modified so that the sprite executes the code in other statuses. One common state is 2, which means the sprite is dying. In this area, we can note that it calls other routines that we're going to detail further along in the tutorial. For now, it's important to know that below, we callJSR InteractMarioSprite
. This is where we will execute the code for the sprite's logic.
- .AlwaysExecutedZone which encompasses the area from the beginning of the routine until the first check
State Machines
A state machine is made up of 2 main parts, the states and the transitions between states. In these machines, only one state executes at a time, and it changes according to logical conditions implemented within each state.
This isn't a complete course on state machines, because this material can take semesters of study for deepening all the distinct dimensions. Nevertheless, we will use this concept for putting together the logic of our sprite.
With this scheme, the idea is to take the central routine called StateMachine, which will be used for calling the correct routine according to the state that's executing. To do this, we will need a table of sprites which we'll use for this purpose. It's highly recommended to use a misc table, so we don't need to find freeram that can end up being used by other resources. For this we have to look at the top of the code, in the marked zone with the comments:
;###################################### ;############## Defines ############### ;######################################
We can add the variable:
!State = !SpriteMiscTable8
Using one of the misc sprite tables that can be used for whatever purpose we want.
Once this is done, we will need to give this variable a value of 0. We will use the state 0 for our initial state. Now we mustn't always initialize it as 0. For example, we could use the extra byte or extra property to set the initial state of the sprite, to create different versions of the same sprite, but normally we use the state 0 as the initial state. To do this, we will add the line on SpriteInit:
STZ !State,x ;!State,x = 0
Soon we'll create a routine named "StateMachine" that executes a different routine, depending on the variable !State,x
. This routine will be the following:
StateMachine: LDA !State,x ;A Reg = !State,x ASL TAX ;Transform A Reg into a index value for table States and put that value in the X Reg JSR (States,x) ;Call Routine on the table States using X reg value. RTS States: dw State0 dw State1 dw State2 . . .
We can note that this routine uses a table named "States". In this table, we will put all the states that our sprite can have as it's running, being stopped, turning, dying, etc. It isn't necessary to put the name of the states "State0". Simply use the name that you think is most conventient. Now normally, it's recommended to number them because it serves to remember the value of the variable !State,x
that's used to call each state.
For those that know some high level programming, this routine would be the equivalent of:
switch(state) { case 0: state0(); break; case 1: state1(); break; case 2: state2(); break; case 3: state3(); break; etc... }