Banner
Views: 779,487,807
Time:
6 users online: bandicoot, h.carrell, Marcozzo Daro,  musicalman,  Ninja Boy, Zandro - Guests: 34 - Bots: 261 Users: 40,858 (1,671 active)
Latest: GreatRomHacker
Tip: You can draw more event tiles under the default Layer 2 Event tiles on the overworld for custom use!Not logged in.
Sprite Creation Workshops using Dyzen with anonimzwx
Forum Index - SMW Hacking - SMW Hacking Help - Tutorials - Sprite Creation Workshops using Dyzen with anonimzwx
Pages: « 1 »
Hey guys, i will do a livestreamings 1 per week doing differents sprites using my tool and teaching how to create them.

I will advice every stream on Discord.

I will put all the streams on this threads, also i will put the routines that i used and the sprites created here.

Download Dyzen V1.0.0.2

Excuse me for the bad english on my videos.

Next Stream in English: August 22 at 8pm GMT-4 on my channel

Siguiente Stream en Español: 15 de Agosto a las 8pm GMT-4 en el canal de la Fortaleza Reznor

Routines:

Interactions:

Interaction routines can be called on Hitboxes Actions generated by Dyzen, for example DefaultAction.





Math:



Actions:

Things that can do the sprite:





Streams:

Dyzen Workshop 1: Creating a basic solid Flying Platform in English
Taller de Dyzen 1: Plataforma voladora basica y solida en Español
Stream 1 Log
Download



Dyzen Workshop 2: Creating a Bloody Grinder in English
Taller de Dyzen 2: Bloody Grinder en español
Stream 2 Log
Download



Dyzen Workshop 3: Creating an Explosive Bowling Ball in English
Taller de Dyzen 3: Explosive Bowling Ball en español
Stream 3 Log
Download



Dyzen Workshop 3: Creating Clown Kart in English
Taller de Dyzen 4: Clown Kart en español


Stream 1 Step By Step: Flying Platform

Step 1: Create frames on Dyzen

Step 2: Create Animation on Dyzen

Step 3: Create Interaction on Dyzen

Step 4: Extracting Resources from Dyzen


Move the sprite generated by the tool to the Sprite Folder of Pixi

Step 5: Doing the CFG

Use CFG.exe to do the CFG for the sprite

Step 6: Convert Sprite From Giepy to Pixi

This step is necessary because Dyzen use Giepy by default, on the future it will use Pixi.

We change the following lines to pixi:

Code
JSL SubOffScreen -> %SubOffScreen()
JSL GetDrawInfo -> %GetDrawInfo()
JSL SubHorzPos -> %SubHorzPos()
JSL SubVertPos -> %SubVertPos()


Also in this zone:

Code
	%SubVertPos()         
	LDA !ScratchE      


We replace:

Code
!ScratchE


For:

Code
!ScratchF


Step 7: Inserting the sprite with pixi

Step 8: Creating interaction


We copy paste this routine at the end of the file:

Solid Interaction

And then on DefaultAction we add this line:

Code
JSR SolidInteraction


Then we go to this section of the code:

Code
;######################################
;############## Defines ###############
;######################################

!FrameIndex = !SpriteMiscTable1
!AnimationTimer = !SpriteDecTimer1
!AnimationIndex = !SpriteMiscTable2
!AnimationFrameIndex = !SpriteMiscTable3
!LocalFlip = !SpriteMiscTable4
!GlobalFlip = !SpriteMiscTable5


And we add this line:

Code
!PlayerRidingPlatform = !SpriteMiscTable10


On the Sprite Code, on this section:

Code
	JSR InteractMarioSprite


We replace it for:

Code
	STZ !PlayerRidingPlatform,x		;By default, the player is not riding the platform
    JSR InteractMarioSprite


Step 9: Moving the sprite in X Axis

We go to this section of the code:

Code
;Here you can write your sprite code routine


Then we add a routine of movement called move:

Code
JSR move


Now we create the movement routine on this section of the code:

Code
;######################################
;######## Sub Routine Space ###########
;######################################

;Here you can write routines or tables


This is the routine:

Code
move:
RTS


Now to move the sprite we use the routine $018022, to use it we add it to the move routine:

Code
move:
	JSL $018022|!rom ;the |!rom is to do it SA-1 Compatible
RTS


Now we must set the Sprite Speed for that we create at the start of the file a constant for the speed:

Code
;Constants
!Xspeed = #$08


Values between #$00 and #$7F are to move sprite to right, Values between #$80 and #$FF are to left, if the value is nearest to Zero the sprite moves slower and it if nearest to #$80, the sprite moves faster.

Now on the Sprite Init Routine, on this section:

Code
    ;Here you can write your Init Code
    ;This will be excecuted when the sprite is spawned


We add 2 lines to set the sprite X speed:

Code
	LDA !Xspeed ;A = !Xspeed
	STA !SpriteXSpeed,x ;!SpriteXSpeed,x = A


Step 10: Moves Player with platform in X-Axis

To do this, first we get the position of the sprite before move it on X-Axis, then we calculate the position of the sprite after move it on the X-axis, Then we calculate a Delta X position and we add that Delta to the Player X Position.

Doing this, move routine will be like this:

Code
move:
	;Sprite X Last Position
	;Sprite X Current position
	;Delta X = Sprite X Current position - Sprite X Last Position
	;Player X position = Player X position + Delta X
	LDA !SpriteXHigh,x
	XBA 
	LDA !SpriteXLow,x
	REP #$20
	STA !Scratch0 ; !Scratch0 = Sprite X Last Position
	SEP #$20
	JSL $018022|!rom

	LDA !PlayerRidingPlatform,x
	BEQ +
	LDA !SpriteXHigh,x
	XBA 
	LDA !SpriteXLow,x
	REP #$20
	;A = Sprite X Current position
	SEC
	SBC !Scratch0
	;A = Delta X
	CLC
	ADC !PlayerX
	STA !PlayerX	;Player X position = Player X position + Delta X
	SEP #$20
+
RTS


The !PlayerRidingPlatform,x is a check to do that only if the player is riding the platform.

Step 11: Wave Motion

Go to this line:

Code
;Don't Delete or write another >Section Graphics or >End Section
;All code between >Section Graphics and >End Graphics Section will be changed by Dyzen : Sprite Maker
;>Section Graphics
;######################################
;########## Graphics Space ############
;######################################


And add copy the following routines:
Sin Routine
Wave Motion Routine

Sin routine, recieve as parameter an angle and a ratio and returns Ratio*Sin(Angle). Read the routine for more details.

Wave motion moves the sprites in Y Axis doing wave motion dah.

Now go to the Defines and below this:

Code


Add this defines:

Code
!AngleLow = !SpriteMiscTable6               ;Angle low byte used for sin movement.
!AngleHigh = !SpriteMiscTable7              ;Angle high byte used for sin movement.
!InitialYLow = !SpriteMiscTable8            ;Start Initial Y position Low byte
!InitialYHigh = !SpriteMiscTable9           ;Start Initial Y position High byte


Now below:

Code
!Xspeed = #$08 ; #$00 - #$7F = Right, #$FF - #$80 = Left 


Add the following constants:

Code
!Ratio = #$20           ;Ratio used for the Sin Movement, higher value then the sprite moves higher and lower
!AngularSpeed = #$0002  ;Angular speed used for the Sin Movement, higher value = faster movement in Y axis


You can change the values to changes the wave motion.

Now call the routine Wave, on the move routine, it should be like this:

Code
move:
	;Sprite X Last Position
	;Sprite X Current position
	;Delta X = Sprite X Current position - Sprite X Last Position
	;Player X position = Player X position + Delta X
	LDA !SpriteXHigh,x
	XBA 
	LDA !SpriteXLow,x
	REP #$20
	STA !Scratch0 ; !Scratch0 = Sprite X Last Position
	SEP #$20
	JSL $018022|!rom

	LDA !PlayerRidingPlatform,x
	BEQ +
	LDA !SpriteXHigh,x
	XBA 
	LDA !SpriteXLow,x
	REP #$20
	;A = Sprite X Current position
	SEC
	SBC !Scratch0
	;A = Delta X
	CLC
	ADC !PlayerX
	STA !PlayerX	;Player X position = Player X position + Delta X
	SEP #$20
+
	JSR Wave

RTS



Step 12: Moves Player with platform in Y-Axis

This step is analogue to Step 10 but in Y-Axis, if you do this move routine will be this:

Code
move:
	;Sprite X Last Position
	;Sprite X Current position
	;Delta X = Sprite X Current position - Sprite X Last Position
	;Player X position = Player X position + Delta X
	LDA !SpriteXHigh,x
	XBA 
	LDA !SpriteXLow,x
	REP #$20
	STA !Scratch0 ; !Scratch0 = Sprite X Last Position
	SEP #$20
	JSL $018022|!rom

	LDA !PlayerRidingPlatform,x
	BEQ +
	LDA !SpriteXHigh,x
	XBA 
	LDA !SpriteXLow,x
	REP #$20
	;A = Sprite X Current position
	SEC
	SBC !Scratch0
	;A = Delta X
	CLC
	ADC !PlayerX
	STA !PlayerX
	SEP #$20
+

	LDA !SpriteYHigh,x
	XBA 
	LDA !SpriteYLow,x
	REP #$20
	STA !ScratchE ; !ScratchE = Sprite X Last Position, We use E because 0 is used by Wave
	SEP #$20

	JSR Wave

	LDA !PlayerRidingPlatform,x
	BEQ +
	LDA !SpriteYHigh,x
	XBA 
	LDA !SpriteYLow,x
	REP #$20
	;A = Sprite X Current position
	SEC
	SBC !ScratchE
	;A = Delta X
	CLC
	ADC !PlayerY
	STA !PlayerY
	SEP #$20
+

RTS


Result:


Stream 2 Step By Step: Bloody Grinder

Step 1: Create frames on Dyzen

Step 2: Create Animation on Dyzen

Step 3: Extracting Resources from Dyzen


Move the sprite generated by the tool to the Sprite Folder of Pixi

Step 4: Doing the CFG

Use CFG.exe to do the CFG for the sprite

Step 5: Convert Sprite From Giepy to Pixi

This step is necessary because Dyzen use Giepy by default, on the future it will use Pixi.

We change the following lines to pixi:

Code
JSL SubOffScreen -> %SubOffScreen()
JSL GetDrawInfo -> %GetDrawInfo()


Step 6: Inserting the sprite with pixi

Step 7: Creating interaction

In this case we will use the default Super Mario World Interaction, For that, i will use Object Clipping 00 and Sprite Clipping 00.

Then i will create an Interaction with Player Routine, I usually put the interaction routine on the bottom of the file:

Code
InteractionWithPlayer:
RTS


And call it the routine after %SubOffScreen():

Code
	JSR InteractionWithPlayer


Now this routine will use 3 routines:

JSL $03B664|!rom: Load player clipping on the scratch rams:

-$00 = X Position Player + X Hitbox Disp. Low Byte
-$01 = Y Position Player + Y Disp. Low Byte
-$08 = X Position Player + X Hitbox Disp. Low Byte
-$09 = Y Position Player + Y Disp. Low Byte
-$02 = Hitbox Width
-$03 = Hitbox Height

JSL $03B69F|!rom: Load sprite clipping on the scratch rams:

-$04 = X Position Sprite + X Hitbox Disp. Low Byte
-$05 = Y Position Sprite + Y Disp. Low Byte
-$0A = X Position Sprite + X Hitbox Disp. Low Byte
-$0B = Y Position Sprite + Y Disp. Low Byte
-$06 = Hitbox Width
-$07 = Hitbox Height

JSL $03B72B|!rom: Check clippings loads to the scratch ram, returns Carry Set if interaction exists and Carry clear if it doesn't.

Then after that routine i will use BCC to don't excecute interaction if the sprite is not touching the player.

The interaction with player will be like this:

Code
InteractionWithPlayer:
	JSL $03B664|!rom
	;$00 = X Position Player + X Hitbox Disp. Low Byte
	;$01 = Y Position Player + Y Disp.	Low Byte
	;$08 = X Position Player + X Hitbox Disp. Low Byte
	;$09 = Y Position Player + Y Disp.	Low Byte
	;$02 = Hitbox Width
	;$03 = Hitbox Height
	JSL $03B69F|!rom
	;$04 = X Position Sprite + X Hitbox Disp. Low Byte
	;$05 = Y Position Sprite + Y Disp.	Low Byte
	;$0A = X Position Sprite + X Hitbox Disp. Low Byte
	;$0B = Y Position Sprite + Y Disp.	Low Byte
	;$06 = Hitbox Width
	;$07 = Hitbox Height
	JSL $03B72B|!rom
	;Carry set if interaction Exist
	;Carry clear if doesnt exist
	BCC +
	;This happends when interaction exists
+
RTS


Now we will copy paste this routine for Spiky Interaction:

Spiky Interaction

And we will call it on the InteractionWithPlayer routine:

Code
InteractionWithPlayer:
	JSL $03B664|!rom
	;$00 = X Position Player + X Hitbox Disp. Low Byte
	;$01 = Y Position Player + Y Disp.	Low Byte
	;$08 = X Position Player + X Hitbox Disp. Low Byte
	;$09 = Y Position Player + Y Disp.	Low Byte
	;$02 = Hitbox Width
	;$03 = Hitbox Height
	JSL $03B69F|!rom
	;$04 = X Position Sprite + X Hitbox Disp. Low Byte
	;$05 = Y Position Sprite + Y Disp.	Low Byte
	;$0A = X Position Sprite + X Hitbox Disp. Low Byte
	;$0B = Y Position Sprite + Y Disp.	Low Byte
	;$06 = Hitbox Width
	;$07 = Hitbox Height
	JSL $03B72B|!rom
	;Carry set if interaction Exist
	;Carry clear if doesnt exist
	BCC +
	;This happends when interaction exists
	JSR SpikyInteraction
+
RTS


Step 8: Playing Grinder Sound

First we will create a constant that plays, it will define every how many frames the sprite must play the sound:

Code
;Constant
!SoundEffectTime = $03 	;$00 = reproduce sound every frame
			;$01 = reproduce sound every 2 frames
			;$03 = reproduce sound every 4 frames
			;$07 = reproduce sound every 8 frames
			;$0F = reproduce sound every 16 frames
			;$1F = reproduce sound every 32 frames
			;$3F = reproduce sound every 64 frames
			;$7F = reproduce sound every 128 frames
			;$FF = reproduce sound every 256 frames


Now we will create a main routine for the sprite on the routine space:

Code
;######################################
;######## Sub Routine Space ###########
;######################################
mainRoutine:
RTS


We will call this routine on the sprite code, for that go to this zone:

Code
;Here you can write your sprite code routine


And add the line:

Code
	JSR mainRoutine


Now we create a routine for play sound after the mainRoutine:

Code
PlaySound:
RTS


We will use the RAM Address $14 for the timer, we do AND with the constant:

Code
PlaySound:
	LDA !EffectiveFrameCounter ;$14
	AND #!SoundEffectTime
RTS


Now A clear all bits except the bits sets of #!SoundEffectTime, if those bits are 0 then it should play a sound, otherwise return:

Code
PlaySound:
	LDA !EffectiveFrameCounter ;$14
	AND #!SoundEffectTime
	BNE +	;If the bits are 0 then return
	LDA #$1A	;Otherwise
	STA $1DF9|!addr	;Play Grinder Sound
+
RTS


Now we call the PlaySound routine from mainRoutine:

Code
mainRoutine:
	JSR PlaySound
RTS


Step 9: Following the player

To do this, we will need to use a routine that checks where is the player. This routine will be CheckPlayerSide:

Code
CheckPlayerSide:
RTS


To do this routine (after mainRoutine) we will compare player position with sprite position:

Code
CheckPlayerSide:

	LDA !SpriteXLow,x	;\
	STA !Scratch0		;|Loads Sprite X position on Scratch 0
	LDA !SpriteXHigh,x	;|
	STA !Scratch1		;/

	REP #$20		;A of 16 bits
	LDA !PlayerX		;A = Player X Position
	CMP !Scratch0		;Compare Player X position with Sprite X position
	SEP #$20		;A of 8 bits

RTS


Then when we call CheckPlayerSide, Carry will be set if the Player X position is higher than Sprite X position (player on the right), otherwise Carry clear.

Now we create a routine for to follow the player:

Code
FollowPlayer:
RTS


Also we will create 2 constants more, !Acceleration and !MaxXSpeed:

Code
;Constant
!Acceleration = $01	;Acceleration of the sprite
!MaxXSpeed = $20 ;$00-$7F right, $80-$FF left
!SoundEffectTime = $03 	;$00 = reproduce sound every frame
			;$01 = reproduce sound every 2 frames
			;$03 = reproduce sound every 4 frames
			;$07 = reproduce sound every 8 frames
			;$0F = reproduce sound every 16 frames
			;$1F = reproduce sound every 32 frames
			;$3F = reproduce sound every 64 frames
			;$7F = reproduce sound every 128 frames
			;$FF = reproduce sound every 256 frames


This routine will do this:

Check if the player is on the right or left side.

if the player is on the left side:
2.1° !SpriteXSpeed,x = !SpriteXSpeed,x-!Acceleration
2.2° if !SpriteXSpeed,x >= 0 dont check max speed, otherwise we check !Maxspeed, if !SpriteXSpeed,x<0 and !SpriteXSpeed,x < -!MaxXSpeed then !SpriteXSpeed,x = -!MaxXSpeed

if the player is on the right side:
3.1° !SpriteXSpeed,x = !SpriteXSpeed,x+!Acceleration
3.2° if !SpriteXSpeed,x < 0 dont check max speed, otherwise we check !Maxspeed, if !SpriteXSpeed,x>0 and !SpriteXSpeed,x >= !MaxXSpeed then !SpriteXSpeed,x = !MaxXSpeed

Code
;This routine follows the player with acceleration and Max speed to do it smoothier
FollowPlayer:
	JSR CheckPlayerSide	;Check the side of the player
	BCS .right
.left

	LDA !SpriteXSpeed,x	;if the player is on the left side
	CLC
	ADC #-!Acceleration
	STA !SpriteXSpeed,x	;!SpriteXSpeed,x = !SpriteXSpeed,x-!Acceleration
	BPL +	;if !SpriteXSpeed,x >= 0 dont check max speed

	CMP #-!MaxXSpeed
	BCS +	;if !SpriteXSpeed,x<0 and 
		;!SpriteXSpeed,x < -!MaxXSpeed then !SpriteXSpeed,x = -!MaxXSpeed
	LDA #-!MaxXSpeed
	STA !SpriteXSpeed,x	
+
RTS

.right

	LDA !SpriteXSpeed,x	;if the player is on the right side
	CLC
	ADC #!Acceleration	
	STA !SpriteXSpeed,x	;!SpriteXSpeed,x = !SpriteXSpeed,x+!Acceleration
	BMI +	;if !SpriteXSpeed,x < 0 dont check max speed
	CMP #!MaxXSpeed
	BCC +	;if !SpriteXSpeed,x>=0 and
		;!SpriteXSpeed,x >= !MaxXSpeed then !SpriteXSpeed,x = !MaxXSpeed

	LDA #!MaxXSpeed
	STA !SpriteXSpeed,x	
+
RTS


Now we call the routine from the mainRoutine:

Code
mainRoutine:
	JSR PlaySound
	JSR FollowPlayer
RTS


And we must call the update sprite position routine of SMW:

Code
mainRoutine:
	JSR PlaySound		;Play Grinder Sound
	JSR FollowPlayer	;Follows the player
	JSL $01802A|!rom	;Update position
RTS


Step 10: Jumping using a Timer

We will create a timer to do the sprite jump, when the timer is zero, the sprite will jump. For that we will define a constant for !JumpMaxTime the say every how many frames jump and other constant !JumpSpeed to set the speed used to jump:

Code
;Constant
!Acceleration = $01	;Acceleration of the sprite
!MaxXSpeed = $20 ;$00-$7F right, $80-$FF left
!JumpMaxTime = $40	;Time used for jumps, $40 = 1 sec, $20 = 0.5 secs
!JumpSpeed = $C0	;Speed used to jump (must be between $80 and $FF)
!SoundEffectTime = $03 	;$00 = reproduce sound every frame
			 			;$01 = reproduce sound every 2 frames
			 			;$03 = reproduce sound every 4 frames
			 			;$07 = reproduce sound every 8 frames
						;$0F = reproduce sound every 16 frames
						;$1F = reproduce sound every 32 frames
						;$3F = reproduce sound every 64 frames
						;$7F = reproduce sound every 128 frames
						;$FF = reproduce sound every 256 frames


Now we will define a RAM Address for Jump timer:

Code
;######################################
;############## Defines ###############
;######################################

!FrameIndex = !SpriteMiscTable1
!AnimationTimer = !SpriteDecTimer1
!AnimationIndex = !SpriteMiscTable2
!AnimationFrameIndex = !SpriteMiscTable3
!LocalFlip = !SpriteMiscTable4
!GlobalFlip = !SpriteMiscTable5
!JumpTimer = !SpriteDecTimer2


Any !SpriteDecTimer works, because those tables decrease in 1 each frame (except if they are 0).

Now we will create a routine for jump after mainRoutine:

Code
JumpWhenJumpTimerIsZero:
RTS


This routine, if the timer is not zero, return, otherwise reset the timer and set jump speed.

Code
;This routine do the sprite jump when the !JumpTimer is 0
JumpWhenJumpTimerIsZero:
	LDA !JumpTimer,x
	BNE +				;If is not 0 then return

	LDA #!JumpMaxTime	;other wise reset the timer
	STA !JumpTimer,x

	LDA !SpriteBlockedStatus_ASB0UDLR,x	;And check floor
	AND #$04 	;A = 0000 0D00
	BEQ +		;If the sprite is not on the floor then don't jump
	LDA #!JumpSpeed
	STA !SpriteYSpeed,x	;Jump
+
RTS


Now we call the routine on mainRoutine before update position:

Code
mainRoutine:
	JSR PlaySound		;Play Grinder Sound
	JSR FollowPlayer	;Follows the player
	JSR JumpWhenJumpTimerIsZero ;Jumps
	JSL $01802A|!rom	;Update position
RTS


Step 11: Climb Walls

We will create first a routine, this will do that when the sprite have positive (or zero) speed, only checks walls from the right, otherwise check walls from the left:

Code
;This routine check walls depends on X Speed of the sprite
CheckWalls:
	JSL $019138|!rom	;interaction with objects routine

	LDA !SpriteXSpeed,x	;A = !SpriteXSpeed,x
	AND #$80			;A = Highest bit of !SpriteXSpeed,x, basically the sign
	CLC					;Clear for ROL
	ROL					;\This moves the highest bit to the lower bit of A, if A was = X000 0000 now it is 0000 000X
	ROL					;/Basically A = sign of the speed
	TAY					;We use Y to index the table CheckWallTable
	LDA !SpriteBlockedStatus_ASB0UDLR,x	;Check Walls
	AND CheckWallTable,y 	;A = 0000 000R if speed is Positive or 0
							;A = 0000 00L0 if speed is Negative
	BEQ +
	SEC				;if is touching a wall return Carry Set
RTS
	CLC				;Otherwise return Carry Clear
RTS


Carry will be set if the routine detects a wall. otherwise zero.

Now we will call this routine from the mainRoutine, before Jump routine:

Code
mainRoutine:
	JSR PlaySound		;Play Grinder Sound
	JSR FollowPlayer	;Follows the player

	JSR CheckWalls

	JSR JumpWhenJumpTimerIsZero ;Jumps
	JSL $01802A|!rom	;Update position
RTS


We create a constant for the climb speed:

Code
;Constant
!Acceleration = $01	;Acceleration of the sprite
!MaxXSpeed = $20 ;$00-$7F right, $80-$FF left
!ObstacleJumpSpeed = $F0	;Speed that use the sprite to climb obstacles (must be between $80 and $FF)
!JumpMaxTime = $40	;Time used for jumps, $40 = 1 sec, $20 = 0.5 secs
!JumpSpeed = $C0	;Speed used to jump (must be between $80 and $FF)
!SoundEffectTime = $03 	;$00 = reproduce sound every frame
			 			;$01 = reproduce sound every 2 frames
			 			;$03 = reproduce sound every 4 frames
			 			;$07 = reproduce sound every 8 frames
						;$0F = reproduce sound every 16 frames
						;$1F = reproduce sound every 32 frames
						;$3F = reproduce sound every 64 frames
						;$7F = reproduce sound every 128 frames
						;$FF = reproduce sound every 256 frames


Now we will check the carry to know if it detects a wall, If there is no contact with walls, then the sprite can jump and update position normally, otherwise the sprite will set its X speed to 0 and it will go to up, using the constant !ObstacleJumpSpeed.

Code
mainRoutine:
	JSR PlaySound	;Play Grinder sound

	JSR FollowPlayer	;Follows the player

	JSR CheckWalls		;Check if it is touching a wall
	BCC .PositionUpdate	;if it is touching a wall then Xspeed = 0 and Y Speed = !ObstacleJumpSpeed
	STZ !SpriteXSpeed,x	
	STZ !SpriteXSpeedAccumulatingFraction,x
	LDA #!ObstacleJumpSpeed
	STA !SpriteYSpeed,x
	JSL $01802A|!rom
RTS

.PositionUpdate			;Otherwise can jump and update position

	JSR JumpWhenJumpTimerIsZero

	JSL $01802A|!rom

RTS


Result


Thanks to your
Bloody Grinder
tutorial, i created this:



ELMYRA: The one from the final level from the Tiny Toons: Buster's Hidden Treasure (Sega Genesis Game). It can chase you and kill you upon contact.

Dear anonimzwx, if you're reading this, i wanted to learn something like:

-Sprite movement with and graphics flipping (plus sprite gravity)
-Connecting animations with the states/routines.


I understand that the next stream is in August 1st, but can you do this favor?
With this, i will make cool sprites.

I wanted to use my Elmyra in my hack.
you never cease to amaze me

--------------------
What-A-Blast! - My WIP Super Mario World hack
**Layout by Erik557


Stream 3 Step By Step: Bowling Ball

Step 1: Create frames on Dyzen

Step 2: Create Animation on Dyzen

Step 3: Create Interaction on Dyzen

Step 4: Extracting Resources from Dyzen


Move the sprite generated by the tool to the Sprite Folder of Pixi

Step 5: Doing the CFG

Use CFG.exe to do the CFG for the sprite. I used Object Clipping 07. We will use 3 extra bytes.

Step 6: Convert Sprite From Giepy to Pixi

This step is necessary because Dyzen use Giepy by default, on the future it will use Pixi.

We change the following lines to pixi:

Code
JSL SubOffScreen -> %SubOffScreen()
JSL GetDrawInfo -> %GetDrawInfo()
JSL SubHorzPos -> %SubHorzPos()
JSL SubVertPos -> %SubVertPos()


Also in this zone:

Code
	%SubVertPos()         
	LDA !ScratchE      


We replace:

Code
!ScratchE


For:

Code
!ScratchF


Also we will use Extra Bytes, then we must change the defines of the sprite because it use Giepy ExtraBytes by default, you must change this:

Code
!ExtraByte1 = $4000A4 -> !ExtraByte1 = $400099
!ExtraByte2 = $4000BA -> !ExtraByte2 = $4000AF
!ExtraByte3 = $4000D0 -> !ExtraByte3 = $4000C5
!ExtraByte4 = $4000E6 -> !ExtraByte4 = $4000DB


Step 7: Inserting the sprite with pixi

Step 8: Creating interaction


This step is the same as Bloody Grinder, Check Bloody Grinder Log

Step 9: Main Routine

On the SpriteCode routine we will call a routine Called MainRoutine after interaction with player:

Code
    JSR InteractMarioSprite
    ;After this routine, if the sprite interact with mario, Carry is Set.

	JSR MainRoutine
    ;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


Now on the Sub Routine Space we create the MainRoutine:

Code
MainRoutine:
RTS


Step 10: Bounce

On the Main routine we call update sprite position with gravity routine $01802A:

Code
MainRoutine:
	JSL $01802A|!rom ;Update X and Y Position
RTS


Remember includes |!rom for sa1 compatibility.

Now we create a routine Bounce, the logic of this routine is:

-Each frame we save the last blocked status of the floor on a misc table.
-If the sprite is falling (Y Speed > 0), sprite y speed is more than a minimum speed for bounce, the sprite is touching the floor and on the last blocked status the sprite wasn't touching the floor, then the sprite bounce.
-For bounce we save the half of the current Y Speed and then we invert it, basically New Y Speed = -(Old Y Speed/2). Also we play a sound effect, shake the earth and do the stun.

Then the first step is create a constant on the top of the file for minimum Y speed required for bounce:

Code
;Constant
!MinYSpeedBounce = #$20	;Must be between #$00 and #$7F


Then on the defines space we create the last frame floor blocked status:

Code
;######################################
;############## Defines ###############
;######################################

!FrameIndex = !SpriteMiscTable1
!AnimationTimer = !SpriteDecTimer1
!AnimationIndex = !SpriteMiscTable2
!AnimationFrameIndex = !SpriteMiscTable3
!LocalFlip = !SpriteMiscTable4
!GlobalFlip = !SpriteMiscTable5
!LastBlockedFloorState = !SpriteMiscTable6


This must start with 0, then on the Init we set it to zero:

Code
;######################################
;########### Init Routine #############
;######################################
print "INIT ",pc
	LDA #$00
	STA !GlobalFlip,x
	STA !LastBlockedFloorState,x
	JSL InitWrapperChangeAnimationFromStart
RTL


Now we create a bounce routine:

Code
Bounce:
RTS


First step is know if the sprite is falling, for that we check if Y Speed > 0.

Code
Bounce:

	LDA !SpriteYSpeed,x
	BMI .ret
	BEQ .ret				;if Sprite is falling

.ret
RTS


Now we must check if the Y Speed >= !MinYSpeedBounce

Code
Bounce:

	LDA !SpriteYSpeed,x
	BMI .ret
	BEQ .ret				;if Sprite is falling
	CMP !MinYSpeedBounce
	BCC .ret				;if Y Speed >= !MinYSpeedBounce 
.ret
RTS


Now we check if the sprite is touching the floor:

Code
Bounce:

	LDA !SpriteYSpeed,x
	BMI .ret
	BEQ .ret				;if Sprite is falling
	CMP !MinYSpeedBounce
	BCC .ret				;if Y Speed >= !MinYSpeedBounce 

	LDA !SpriteBlockedStatus_ASB0UDLR,x
	AND #$04 ;0000 0D00;
	BEQ .ret				;If sprite is touching the floor
.ret
RTS


Now we check if the last floor blocked status was on the floor or in the air:

Code
Bounce:

	LDA !SpriteYSpeed,x
	BMI .ret
	BEQ .ret				;if Sprite is falling
	CMP !MinYSpeedBounce
	BCC .ret				;if Y Speed >= !MinYSpeedBounce 

	LDA !SpriteBlockedStatus_ASB0UDLR,x
	AND #$04 ;0000 0D00;
	BEQ .ret				;If sprite is touching the floor
	CMP !LastBlockedFloorState,x
	BEQ .ret				;If sprite doesn't touch the floor the last frame
.ret
RTS


Now we do the sprite bounce, play the sound and shake the earth, for sound we use $1DFC and for earthquake we set the timer on $1887:

Code
Bounce:

	LDA !SpriteYSpeed,x
	BMI .ret
	BEQ .ret				;if Sprite is falling
	CMP !MinYSpeedBounce
	BCC .ret				;if Y Speed >= !MinYSpeedBounce 

	LDA !SpriteBlockedStatus_ASB0UDLR,x
	AND #$04 ;0000 0D00;
	BEQ .ret				;If sprite is touching the floor
	CMP !LastBlockedFloorState,x
	BEQ .ret				;If sprite doesn't touch the floor the last frame

	LDA #$25
	STA $1DFC|!addr			;Reproduce Sound

	LDA !SpriteYSpeed,x
	LSR
	STA !Scratch0			;!Scratch0 = YSpeed /2
	STA $1887|!addr			;Set the Earthquake

	LDA #$00
	SEC
	SBC !Scratch0
	STA !SpriteYSpeed,x 	;!SpriteYSpeed,x = -!SpriteYSpeed,x
.ret
RTS


For stun we check player floor blocked status and then we set the stun:

Code
Bounce:

	LDA !SpriteYSpeed,x
	BMI .ret
	BEQ .ret				;if Sprite is falling
	CMP !MinYSpeedBounce
	BCC .ret				;if Y Speed >= !MinYSpeedBounce 

	LDA !SpriteBlockedStatus_ASB0UDLR,x
	AND #$04 ;0000 0D00;
	BEQ .ret				;If sprite is touching the floor
	CMP !LastBlockedFloorState,x
	BEQ .ret				;If sprite doesn't touch the floor the last frame

	LDA #$25
	STA $1DFC|!addr			;Reproduce Sound

	LDA !SpriteYSpeed,x
	LSR
	STA !Scratch0			;!Scratch0 = YSpeed /2
	STA $1887|!addr			;Set the Earthquake

	LDA #$00
	SEC
	SBC !Scratch0
	STA !SpriteYSpeed,x 	;!SpriteYSpeed,x = -!SpriteYSpeed,x

	LDA !PlayerBlockedStatus_S00MUDLR
	AND #$04
	BEQ +					;If player is touching the floor

	LDA !Scratch0
	STA $18BD|!addr			;Set Stun Time

+
.ret
RTS


As last step we update the last floor blocked status:

Code
Bounce:
	LDA !SpriteYSpeed,x
	BMI .ret
	BEQ .ret				;if Sprite is falling
	CMP !MinYSpeedBounce
	BCC .ret

	LDA !SpriteBlockedStatus_ASB0UDLR,x
	AND #$04 ;0000 0D00;
	BEQ .ret				;If sprite is touching the floor
	CMP !LastBlockedFloorState,x
	BEQ .ret				;If sprite doesn't touch the floor the last frame

	LDA #$25
	STA $1DFC|!addr			;Reproduce Sound

	LDA !SpriteYSpeed,x
	LSR
	STA !Scratch0			;!Scratch0 = YSpeed /2
	STA $1887|!addr			;Set the Earthquake

	LDA !PlayerBlockedStatus_S00MUDLR
	AND #$04
	BEQ +					;If player is touching the floor

	LDA !Scratch0
	STA $18BD|!addr			;Set Stun Time

+

	LDA #$00
	SEC
	SBC !Scratch0
	STA !SpriteYSpeed,x 	;!SpriteYSpeed,x = -!SpriteYSpeed,x

.ret
	LDA !SpriteBlockedStatus_ASB0UDLR,x
	AND #$04 ;0000 0D00;
	STA !LastBlockedFloorState,x
RTS


Then we call the routine on the MainRoutine before update position:

Code
MainRoutine:
	JSR Bounce
	JSL $01802A|!rom ;Update X and Y Position
RTS


Step 11: Basic X Speed

For this step we create 2 constants: !RotationTime and !XSpeed.

-!RotationTime: Will be used to set how fast the sprite will rotate, it is the time to update the current frame of the animation. More Time, slower rotation.
-!XSpeed: X Speed of the sprite when it touch the floor for the first time.

Then we create both on the top of the file:

Code
;Constant
!MinYSpeedBounce = #$20 ;Minimum Sprite Y Speed to Bounce (Must be between #$00 and #$7F)	
!RotationTime = $04	;Time to update animation
!XSpeed = #$22		;X Speed that have the sprite when it touch the floor for the first time.


Now we will create a routine called XMovement that we will use it to set the X Speed, for that routine we will need a misc table to know when the sprite touch the floor for the first time.

Code
;######################################
;############## Defines ###############
;######################################

!FrameIndex = !SpriteMiscTable1
!AnimationTimer = !SpriteDecTimer1
!AnimationIndex = !SpriteMiscTable2
!AnimationFrameIndex = !SpriteMiscTable3
!LocalFlip = !SpriteMiscTable4
!GlobalFlip = !SpriteMiscTable5
!LastBlockedFloorState = !SpriteMiscTable6
!TouchedFloorFlag = !SpriteMiscTable7


This misc must start with 0:

Code
;######################################
;########### Init Routine #############
;######################################
print "INIT ",pc
	LDA #$00
	STA !GlobalFlip,x
	STA !LastBlockedFloorState,x
	STA !TouchedFloorFlag,x
	JSL InitWrapperChangeAnimationFromStart
	
    ;Here you can write your Init Code
    ;This will be excecuted when the sprite is spawned 
RTL


Now we create the routine on the sub routine space:

Code
XMovement:
RTS


The logic of this routine is:

-If The sprite never touched the floor and now the sprite is touching the floor then we update the !TouchedFloorFlag and we set the speed.
-If the sprite is touching a wall then invert the Xspeed (!SpriteXSpeed,x = -!SpriteXSpeed,x)

Then first we check the !TouchedFloorFlag to know if it never touched the floor:

Code
XMovement:
	LDA !TouchedFloorFlag,x
	BEQ +
+
RTS


Now we check if the sprite is touching the floor, update !TouchedFloorFlag and Xspeed:

Code
XMovement:
	LDA !TouchedFloorFlag,x
	BNE +
	LDA !SpriteBlockedStatus_ASB0UDLR,x
	AND #$04		;0000 00LR
	BEQ +			;If sprite is touching the floor

	LDA #$01
	STA !TouchedFloorFlag,x
	LDA !XSpeed
	STA !SpriteXSpeed,x
+
RTS


Now we check the walls and invert X Speed:

Code
XMovement:
	LDA !TouchedFloorFlag,x
	BNE +
	LDA !SpriteBlockedStatus_ASB0UDLR,x
	AND #$04		;0000 00LR
	BEQ +			;If sprite is touching the floor

	LDA #$01
	STA !TouchedFloorFlag,x
	LDA !XSpeed
	STA !SpriteXSpeed,x
+

	LDA !SpriteBlockedStatus_ASB0UDLR,x
	AND #$03		;0000 00LR
	BEQ +			;Check Walls

	LDA #$00
	SEC
	SBC !SpriteXSpeed,x
	STA !SpriteXSpeed,x 	;!SpriteXSpeed,x = -!SpriteXSpeed,x

+
RTS


Now we call the routine on the MainRoutine after bounce:

Code
MainRoutine:
	JSR Bounce
	JSR XMovement
	JSL $01802A|!rom ;Update X and Y Position
RTS


If you insert the sprite now the sprite will do the movement fine but the animation will not flip, usually for a normal sprite you flip the sprite using !GlobalFlip,x, basically if it is 0 then it is not flipped and if it 1 then the sprite is flipped, but that for this sprite is not a good idea because it won't looks fine. To do this sprite flip, we will go to the animation routine to this zone:

Code
	REP #$30						;A,X/Y of 16 bits
	LDX !Scratch4					;X = sprite index in 16 bits

	LDA !Scratch0
	ASL
	TAY								;Y = 2*Animation index

	INC !Scratch2					;New Animation Frame Index = Animation Frame Index + 1

	LDA !Scratch2			        ;if Animation Frame index < Animation Lenght then Animation Frame index++
	CMP AnimationLenght,y			;else go to the frame where start the loop.
	BCC +							

	LDA AnimationLastTransition,y
	STA !Scratch2					;New Animation Frame Index = first frame of the loop.

+
	LDA !Scratch2
	CLC
	ADC AnimationIndexer,y
	TAY								;Y = Position of the first frame of the animation + animation frame index

	SEP #$20						;A of 8 bits


In this Zone the Scratch2 have the index current frame that the sprite must show, by default frame always Increase in 1 and when it is the last frame (in this case frame #$000B then it is set to 0). We will change that to allows decrease or increase frame depends on XSpeed. Then for that on this zone:

Code
AnimationRoutine:
    LDA !AnimationTimer,x
    BEQ +

	RTS

+


We will use ScratchE to save the sign of the speed. it will be 0 if the speed is positive and 80 if negative:

Code
AnimationRoutine:
    LDA !AnimationTimer,x
    BEQ +

	RTS

+

	STZ !ScratchF
	LDA !SpriteXSpeed,x
	AND #$80
	STA !ScratchE


Now on the other zone we will make the following:

-If Sprite X Speed < 0 then Frame Increase and if the current frame > last frame then is 0 otherwise Frame Decrease and if the frame is negative then now is the last frame

Code
	REP #$30						;A7X/Y of 16 bits
	LDX !Scratch4					;X = sprite index in 16 bits

	LDA !Scratch0
	ASL
	TAY								;Y = 2*Animation index

	LDA !ScratchE
	BNE +

	DEC !Scratch2

	LDA !Scratch2
	BPL ++

	LDA #$000B
	STA !Scratch2
	BRA ++

+
	INC !Scratch2					;New Animation Frame Index = Animation Frame Index + 1

	LDA !Scratch2			        ;if Animation Frame index < Animation Lenght then Animation Frame index++
	CMP AnimationLenght,y			;else go to the frame where start the loop.
	BCC ++							

	LDA AnimationLastTransition,y
	STA !Scratch2					;New Animation Frame Index = first frame of the loop.

++
	LDA !Scratch2
	CLC
	ADC AnimationIndexer,y
	TAY								;Y = Position of the first frame of the animation + animation frame index

	SEP #$20						;A of 8 bits


Also we will go to the table Times:

Code
Times:
	
Animation0_Animation0_Times:
	db $04,$04,$04,$04,$04,$04,$04,$04,$04,$04,$04,$04


And we will replace all $04 for !RotationTime:

Code
Times:
	
Animation0_Animation0_Times:
	db !RotationTime,!RotationTime,!RotationTime,!RotationTime,!RotationTime,!RotationTime
	db !RotationTime,!RotationTime,!RotationTime,!RotationTime,!RotationTime,!RotationTime


Now you user can customize !XSpeed and !RotationTime.

Step 12: Explosion

For explosion we will create 2 constants: !MaxTime and !FlashMinTime.

-!MaxTime: Time for do the sprite explode.
-!FlashMinTime: Time for do the sprite flash before explode.

Then we add them with the others constants:

Code
;Constant
!MinYSpeedBounce = #$20 ;Minimum Sprite Y Speed to Bounce (Must be between #$00 and #$7F)	
!RotationTime = $04	;Time to update animation
!XSpeed = #$22		;X Speed that have the sprite when it touch the floor for the first time.
!MaxTime = #$FF 	;FF = 4 seconds
!FlashMinTime = #$30	;Minimum Time to start to flash


Also we need a timer for explosion, for that we add it to the defines:

Code
;######################################
;############## Defines ###############
;######################################

!FrameIndex = !SpriteMiscTable1
!AnimationTimer = !SpriteDecTimer1
!AnimationIndex = !SpriteMiscTable2
!AnimationFrameIndex = !SpriteMiscTable3
!LocalFlip = !SpriteMiscTable4
!GlobalFlip = !SpriteMiscTable5
!LastBlockedFloorState = !SpriteMiscTable6
!TouchedFloorFlag = !SpriteMiscTable7
!ExplosionTimer = !SpriteDecTimer2


You always use DecTimers for timers. Now we must se the timer on the init:

Code
;######################################
;########### Init Routine #############
;######################################
print "INIT ",pc
	LDA #$00
	STA !GlobalFlip,x
	STA !LastBlockedFloorState,x
	STA !TouchedFloorFlag,x
	JSL InitWrapperChangeAnimationFromStart
	LDA !MaxTime
	STA !ExplosionTimer,x
RTL


And we will copy paste this routine on the sub routine space:

Code
bobomb:
	LDA #$15
	STA $1887|!addr	; shake the ground
	LDA #$0D		;/
	STA !SpriteNumber,x	;\ Sprite = Bob-omb.
	LDA #$08		;/
	STA !SpriteStatus,x	;\ Set status for new sprite.
	JSL $07F7D2|!rom	;/ Reset sprite tables (sprite becomes bob-omb)..
	LDA #$01		;\ .. and flag explosion status.
	STA !SpriteMiscTable8,x	;/
	LDA #$40		;\ Time for explosion.
	STA !SpriteDecTimer1,x
	LDA #$09		;\
	STA $1DFC|!addr	;/ Sound effect.
	LDA #$1B
	STA !SpriteTweaker167A_DPMKSPIS,x
	RTS


That routine replace the sprite with a bob omb exploding.

Now we create a Explosion routine:

Code
Explode:
RTS


The logic of this routine is:

-If Explode Timer == 0 then call bobomb and it will move it 16 pixels to right (this is to center the explosion).

Code
Explode:
	LDA !ExplosionTimer,x
	BNE +		;if timer is 0

	JSR bobomb	;Explode
	LDA !SpriteXHigh,x
	STA !Scratch1
	LDA !SpriteXLow,x
	STA !Scratch0
	REP #$20
	LDA !Scratch0
	CLC
	ADC #$0010
	STA !Scratch0
	SEP #$20
	LDA !Scratch0
	STA !SpriteXLow,x
	LDA !Scratch1
	STA !SpriteXHigh,x	;Moves 16 pixels to right
+
RTS


Also we will add an Extra byte for explosion, Extra Byte 3 will be used for explosion, if it is 0 then explode and if it is not 0 then dont explode, For that on the defines we will define the extra byte:

Code
;######################################
;############## Defines ###############
;######################################

!FrameIndex = !SpriteMiscTable1
!AnimationTimer = !SpriteDecTimer1
!AnimationIndex = !SpriteMiscTable2
!AnimationFrameIndex = !SpriteMiscTable3
!LocalFlip = !SpriteMiscTable4
!GlobalFlip = !SpriteMiscTable5
!LastBlockedFloorState = !SpriteMiscTable6
!TouchedFloorFlag = !SpriteMiscTable7
!ExplosionTimer = !SpriteDecTimer2
!Explode = !ExtraByte3


Then we add that only explode if !Explode is 0:

Code
Explode:
	LDA !Explode,x
	BEQ +		;Check Extra Byte
	LDA !ExplosionTimer,x
	BNE +		;if timer is 0

	JSR bobomb	;Explode
	LDA !SpriteXHigh,x
	STA !Scratch1
	LDA !SpriteXLow,x
	STA !Scratch0
	REP #$20
	LDA !Scratch0
	CLC
	ADC #$0010
	STA !Scratch0
	SEP #$20
	LDA !Scratch0
	STA !SpriteXLow,x
	LDA !Scratch1
	STA !SpriteXHigh,x	;Moves 16 pixels to right
+
RTS


Now we call that routine on the Main Routine After XMovement:

Code
MainRoutine:

	JSR Bounce
	JSR XMovement
	JSR Explode

	JSL $01802A|!rom ;Update X and Y Position
RTS


If you insert the sprite, the sprite wont flash but will do all other things. To make it Flash we go to the Graphic Routine to this zone:

Code
    LDA Properties,x
    STA !TileProperty,y                 ;Set the Tile property of the tile Y


That zone set the properties of the Tile, Properties follows the format YXPPCCCT:

-Y = If 0 then it doesn't flip in Y, if it is 1 it flip in Y
-X = If 0 then it doesn't flip in X , if it is 1 it flip in X
-PP = Priority vs Layers (00 behind all layer, 01 in front layer 2 but behind layer 2, 10 = in front layer 1 and 3, 11 = in front of all)
-CCC = Palette (In this case we use Palette E when doesn't flash and F when it flashes, that is equivalent to 6 and 7)
T = If 0 it uses SP1/2 if 1 it uses SP3/4.

In this case the logic will be clear all CCC bits and replace them with CCC bits of a Scratch.

Then at the start of Graphic Routine we add this:

Code
GraphicRoutine:

    %GetDrawInfo()                     ;Calls GetDrawInfo to get the free slot and the XDisp and YDisp

	LDA #$0C
	STA !ScratchE


ScratchE will be C in the normal case, because C is equivalent to CCC = 110 = 6.

To do the Flash, we will check ExplosionTimer, if it less than !FlashMinTime we will make it Flash.

For Flash we will do an AND #$02, that will alternate the palette every 2 frames, if you want to alternate every 1 frame then you put 1, Valid Values for that and is 01,02,04,08,10,20,40 and 80, Higher value slower flash.

Code
GraphicRoutine:

    %GetDrawInfo()                     ;Calls GetDrawInfo to get the free slot and the XDisp and YDisp

	LDA #$0C
	STA !ScratchE

	LDA !Explode,x
	BEQ +		;If can explode (check extra byte)
	LDA !ExplosionTimer,x
	CMP !FlashMinTime ;if !ExplosionTimer,x<!FlashMinTime
	BCS +		  
	AND #$02
	BNE +		;If is !ExplosionTimer,x Bitwise AND #$02 0
	LDA #$0E
	STA !ScratchE	;Use Palette 7
+


Then we change the other zone for this:

Code
    LDA Properties,x
	AND #$F1							;YXPP000T
	ORA !ScratchE
    STA !TileProperty,y                 ;Set the Tile property of the tile Y


Now the Sprite is Finished.

EXTRA STEP: X Speed Depends on Rotation Time

This step is more complex. Basically we will transform !RotationTime into !XSpeed when the sprite touch the floor for the first time.

For this we will require some Physics knowledge.

This !RotationTime is the time to change the frame, the angle changes in 30°, for that the Complete Period is 12*!RotationTime, because in that time the sprite will do a complete rotation, it is called the Period.

Angular Speed is Equals to (2*Pi)/Period, then that is how we get the Angular Speed.

The Regular Speed is = Angular Speed * Ratio, in this case Ratio of the sprite is 24 pixels. This Regular Speed will be on Pixels / Frame. To transform it to SMW Speed Units we must Multiply by 16.

Obviusly all this calculus is very slow to do on snes, for that we will calculate all those values on a program or excel and create a table based on that. If you do that you will get a table that transform Rotation time into X Speed, Here is the table:

Code
RotToSpeedTable:
db $FF,$C9,$65,$43,$32,$28,$22,$1D,$19,$16,$14,$12,$11,$0F,$0E,$0D
db $0D,$0C,$0B,$0B,$0A,$0A,$09,$09,$08,$08,$08,$07,$07,$07,$07,$06
db $06,$06,$06,$06,$06,$05,$05,$05,$05,$05,$05,$05,$05,$04,$04,$04
db $04,$04,$04,$04,$04,$04,$04,$04,$04,$04,$03,$03,$03,$03,$03,$03
db $03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03
db $03,$02,$02,$02,$02,$02,$02,$02,$02,$02,$02,$02,$02,$02,$02,$02
db $02,$02,$02,$02,$02,$02,$02,$02,$02,$02,$02,$02,$02,$02,$02,$02
db $02,$02,$02,$02,$02,$02,$02,$02,$02,$02,$02,$02,$02,$02,$02,$02
db $02,$02,$02,$02,$02,$02,$02,$01,$01,$01,$01,$01,$01,$01,$01,$01


Now We will create a Define for Rotation Direction, If it is zero rotation will be to left, other wise will be right.

Code
;######################################
;############## Defines ###############
;######################################

!FrameIndex = !SpriteMiscTable1
!AnimationTimer = !SpriteDecTimer1
!AnimationIndex = !SpriteMiscTable2
!AnimationFrameIndex = !SpriteMiscTable3
!LocalFlip = !SpriteMiscTable4
!GlobalFlip = !SpriteMiscTable5
!LastBlockedFloorState = !SpriteMiscTable6
!TouchedFloorFlag = !SpriteMiscTable7
!ExplosionTimer = !SpriteDecTimer2
!RotationDirection = !SpriteMiscTable8
!Explode = !ExtraByte3


Also we will do that this depends on Extra Bit:

Code
;######################################
;########### Init Routine #############
;######################################
print "INIT ",pc
	LDA #$00
	STA !GlobalFlip,x
	STA !LastBlockedFloorState,x
	STA !TouchedFloorFlag,x
	JSL InitWrapperChangeAnimationFromStart
	LDA !MaxTime
	STA !ExplosionTimer,x
	LDA !ExtraBits,x
	BEQ +
	LDA #$01
	STA !RotationDirection,x
+
	
    ;Here you can write your Init Code
    ;This will be excecuted when the sprite is spawned 
RTL


Also to do the sprite easier to customize we will change !RotationTime and !XSpeed to Extra bytes.

Code
;######################################
;############## Defines ###############
;######################################

!FrameIndex = !SpriteMiscTable1
!AnimationTimer = !SpriteDecTimer1
!AnimationIndex = !SpriteMiscTable2
!AnimationFrameIndex = !SpriteMiscTable3
!LocalFlip = !SpriteMiscTable4
!GlobalFlip = !SpriteMiscTable5
!LastBlockedFloorState = !SpriteMiscTable6
!TouchedFloorFlag = !SpriteMiscTable7
!ExplosionTimer = !SpriteDecTimer2
!RotationDirection = !SpriteMiscTable8
!RotationTime = !ExtraByte1
!XSpeed = !ExtraByte2
!Explode = !ExtraByte3


Also now the !XSpeed will be the initial X Speed of the sprite.

Code
;######################################
;########### Init Routine #############
;######################################
print "INIT ",pc
	LDA #$00
	STA !GlobalFlip,x
	STA !LastBlockedFloorState,x
	STA !TouchedFloorFlag,x
	JSL InitWrapperChangeAnimationFromStart
	LDA !MaxTime
	STA !ExplosionTimer,x
	LDA !ExtraBits,x
	BEQ +
	LDA #$01
	STA !RotationDirection,x
+
	LDA !XSpeed,x
	STA !SpriteXSpeed,x
	
    ;Here you can write your Init Code
    ;This will be excecuted when the sprite is spawned 
RTL


Now we will create a routine that use the table, that will transform !RotationTime into Sprite X Speed.

Code
RotationTimeToSpeed:
RTS


The logic of this routine is:

-You can see that the first 2 values are not valid for Speed, because X Speed should be between 00 and 7F, Then we only can index the table starting with 2.
-We will index the table, for that we load !RotationTime into Y register and use it to set the X Speed.
-If Rotation Direction is to Left (0) we invert X Speed.

Code
RotationTimeToSpeed:
	LDA !RotationTime,x
	CMP #$02
	BCS +		;Minimum Index of the table must be 2
	LDA #$02	;If less than 2 then use 2.
+
	TAY		;Y = Rotation Time
	LDA RotToSpeedTable,y
	STA !SpriteXSpeed,x	;Transform Rotation Time into X Speed using the table
	LDA !RotationDirection,x
	BEQ +			;If rotation is to left then invert sprite x speed
	LDA #$00
	SEC
	SBC !SpriteXSpeed,x
	STA !SpriteXSpeed,x	;!SpriteXSpeed,x=-!SpriteXSpeed,x
+
RTS


Now on XMovement routine:

Code
XMovement:
	LDA !TouchedFloorFlag,x
	BNE +
	LDA !SpriteBlockedStatus_ASB0UDLR,x
	AND #$04		;0000 00LR
	BEQ +			;If sprite is touching the floor

	LDA #$01
	STA !TouchedFloorFlag,x
	LDA !XSpeed
	STA !SpriteXSpeed,x
+

	LDA !SpriteBlockedStatus_ASB0UDLR,x
	AND #$03		;0000 00LR
	BEQ +			;Check Walls

	LDA #$00
	SEC
	SBC !SpriteXSpeed,x
	STA !SpriteXSpeed,x 	;!SpriteXSpeed,x = -!SpriteXSpeed,x

+
RTS


We change lines that set speed calling the routine RotationTimeToSpeed, also we only invert RotationDirection when it touch a wall:

Code
XMovement:

	LDA !TouchedFloorFlag,x
	BNE +
	LDA !SpriteBlockedStatus_ASB0UDLR,x
	AND #$04		;0000 00LR
	BEQ +			;If sprite is touching the floor

	LDA #$01
	STA !TouchedFloorFlag,x
	JSR RotationTimeToSpeed
+

	LDA !SpriteBlockedStatus_ASB0UDLR,x
	AND #$03		;0000 00LR
	BEQ +

	LDA !RotationDirection,x
	EOR #$01
	STA !RotationDirection,x

	JSR RotationTimeToSpeed

+

RTS


Also we must change some things on the animation routine, the first is on the ChangeAnimationFromStart, we must do that Times now use only !RotationTime, for that we go to this zone:

Code
ChangeAnimationFromStart:
	STZ !AnimationFrameIndex,x


and we add this:

Code
ChangeAnimationFromStart:
	STZ !AnimationFrameIndex,x

	LDA !RotationTime,x
	STA !ScratchD


Now !ScratchD will be the rotation time, that scratch must be used to change the time, then we go to this line:

Code
	LDA Times,y
	STA !AnimationTimer,x			;Time = Times[New Animation Frame Index]


And Replace it by:

Code
	LDA !ScratchD
	STA !AnimationTimer,x			;Time = Times[New Animation Frame Index]


We must do almost the same on the animation routine, we go to this zone:

Code
AnimationRoutine:
    LDA !AnimationTimer,x
    BEQ +

	RTS

+

	STZ !ScratchF
	LDA !SpriteXSpeed,x
	AND #$80
	STA !ScratchE


and we add change it by:

Code
AnimationRoutine:
    LDA !AnimationTimer,x
    BEQ +

	RTS

+

	LDA !RotationTime,x
	STA !ScratchD
	STZ !ScratchF
	LDA !SpriteXSpeed,x
	AND #$80
	STA !ScratchE


Now we change the line of time:

Code
	LDA !ScratchD
	STA !AnimationTimer,x			;Time = Times[New Animation Frame Index]


Also we must delete Times Table.


And now the animation depends on Rotation Direction and not on Sprite X Speed then we must change this:

Code
AnimationRoutine:
    LDA !AnimationTimer,x
    BEQ +

	RTS

+

	LDA !RotationTime,x
	STA !ScratchD
	STZ !ScratchF
	LDA !RotationDirection,x		
	STA !ScratchE		;!ScratchE = 0 if Speed is positive and not if it is negative


And now the sprite is finished and customizable by the user.

Result:


Check this:



I used this code to make the sprite move:



Add this in the Sprite routine and the sprite will work fine.
Yeah, the only thing i wanted is a SMB3 goomba-like stomp code in the DefaultAction.
Any suggestions?
Probably the next Live stream will be the last, because almost nobody watch them or participate on the chat, i will replace them with normal videos. The sprite of the next livestream will be this:


I'm truly sorry that nobody watched your Dyzen live.

I'm just learning some routines from other sprites stored in this website, now i'll give you some advice for routines for enemies and gimmicks for your sprites.

Like STOMPING AN ENEMY:



You also can make the enemy move:



Are my tips useful? Post here.
Sorry for the last stream i had problems with my internet. That was the last livestream, I will change the format to normal videos, because very few people participate on the livestreams. The log of the stream 4 will be during weekend.

Do i still need alot of asm knowledge in order to make a sprite in dyzen because im trying to recreate the bandit, baseball boys and zues from YI
Originally posted by codfish1002
Do i still need alot of asm knowledge in order to make a sprite in dyzen because im trying to recreate the bandit, baseball boys and zues from YI


There are some things that you can do without asm knowledge, but you always Will need to learn asm to do complex things.

Pages: « 1 »
Forum Index - SMW Hacking - SMW Hacking Help - Tutorials - Sprite Creation Workshops using Dyzen with anonimzwx

The purpose of this site is not to distribute copyrighted material, but to honor one of our favourite games.

Copyright © 2005 - 2019 - SMW Central
Legal Information - Privacy Policy - Link To Us


Total queries: 7

Menu

Follow Us On

  • YouTube
  • Twitch
  • Twitter

Affiliates

  • Talkhaus
  • SMBX Community
  • GTx0
  • Super Luigi Bros
  • ROMhacking.net
  • MFGG
  • Gaming Reinvented