TND Productions, C64 News + Updates


SEUCK REDUX
By Richard Bayliss and Martin Piper

 1. INTRODUCTION

1A. GETTING STARTED
1B. SETTING UP AND TESTING THE SOURCE
1C. IMPORTING YOUR OWN SEUCK GAME DATA INTO THE SOURCE CODE

2. POWER UPS

ADDING POWER UPS

2A. A QUICK EXAMPLE (BORDER CHANGE):
2B. TESTING MORE THAN ONE ENEMY KILLED
2C. BULLET SPEED
2D. CHANGING THE PLAYER'S OBJECT
2E. SETTING DEFAULTS
2F. PROGRESSIVE POWER UPS
2G. OTHER PLAYER PROPERTIES + INFORMATION

3. ENEMY AIM FIRING
ENEMY AIM FUNCTION
3A. SINGLE ENEMY AIM FIRING
3B. MULTIPLE ENEMY AIM FIRING

4. BACKROUND ANIMATION
ADDING BACKGROUND ANIMATION
4A. PARALLAX SCROLLING EXAMPLE
4B. ANIMATED CHARACTER SETS

5. MUSIC / SOUND EFFECTS
MUSIC AND SOUND EFFECTS

5A. MUSIC PLAYERS, FORMAT AND MEMORY
5B. SETTING INIT / PLAY ADDRESSES IN CUSTOM PLAYERS
5C. PLAYING IN GAME MUSIC WITH A DIFFERENT TRACK
5D. PLAYING MUSIC AND SOUND EFFECTS AT THE SAME TIME

6. DATA GROWTH
GENERAL INFORMATION ABOUT DATA GROWTH

7. ADDITIONAL SEUCK REDUX COMMANDS
ADDITIONAL SEUCK REDUX COMMANDS IN ScrollEntry.a


8. MAKING A NEW SCORE PANEL
MAKING A NEW SCORE PANEL

8A. MAKING AN 8 SPRITE SCORE PANEL
8B. MAKING A CHAR BASED SCORE PANEL

9. MAKING A NEW FRONT END
MAKING A NEW FRONT END
9A. PUTTING LOGO, TEXT AND CUSTOM CHAR SET INTO A NEW FRONT END
9B. USING RASTER SPLITS
9C. FINISHING THINGS OFF - DO IT YOUR WAY



1. INTRODUCTION

SEUCK REDUX IS NOT SEUCK!!!

SEUCK now has a special enhancement framework, which uses ACME cross assembler. This frame work is something very special for SEUCK game titles. It will give you the ability to produce QUALITY game productions, inside a brand new source code. To put it another way, SEUCK Redux allows you to make brilliant game creations out of SEUCK. You can create new front ends, add new special features, such as power ups, and even tweak the game to do different things, such as turn random firing into aim functions. Make use out of alien AI, etc. With a coding knowledge you can create commercial quality vertical/horizontal scrolling shoot 'em ups, that uses SEUCK's attack waves and player settings. There's hardly any SEUCK slowdown syndrome, as the code's multiplexer allows up to 32 sprites to be used in the code. There are also some SEUCK example work files which you can play around with, inside the source. SEUCK Redux allows you to import your SEUCK files, which were saved as ALL DATA from the SEUCK/Sideways SEUCK editor. Take a look at GETTING STARTED to see what to do here.


 
 
Legion of the Damned is a prime example of some of a special power up feature. Where both players, Player 1 and Player 2 could press a letter key to cast spells, should any bottles have been picked up. The spells use a kind of smart bomb feature. More bombs picked up, the more powerful the spells would have become. Nyaaaah! - 15th Anniversary Edition uses a tweak to the score board, which is also possible with SEUCK Redux. Nuclear Strike Force and Flying Cobra both feature the test AIM function. Where a selected enemy (which uses random firing) can use the test AIM function.


BACK TO TOP



1A. GETTING STARTED:

So then, would you like to use SEUCK Redux? If the Answer is YES, then let's go on. Before you can USE SEUCK Redux, you will need to download the following PC-based utilities:

C64 TOOLS:

Shoot Em Up Construction Kit or Sideways SEUCK  - For making and saving your old SEUCK game work files (Not Saved finished game state)

SEUCK Revive (CSDB ID: 47771) -
For restoring the SEUCK utility to its form, should any crashing occur during use of the editor (Or should you wish to re-enabled the editor on your standalone SEUCK game) (Vertical scrolling version only).

ESSENTIAL PC TOOLS:

DOSBOX - An MSDos emulator (Current version I use is V0.74)

64Copy - An MSDOS command line tool, which can copy files from one directory to another in C64 format.

RELAUNCH 64 - A text editor, which you can code and assemble your source code. (Requires JAVA7).

MARTIN PIPER'S COMPLETE OPEN SOURCE ARCHIVE (LATEST VERSION)- Contains different source, including the SEUCK Redux source (Scroller), etc. (On the page click Clone or Download) and select DOWNLOAD. Martin's build ACME Cross assembler should also included with the source code. 

OPTIONAL PC TOOLS:
Although the whole source does

EXOMIZER - A fast cruncher, which gives very good results. Optional de-crunch effects, etc.

Assuming that you have now downloaded everything. Open the ZIP archive of the Martin Piper's sources and extract it to the c:\, make the directory. Rename the directory C642016 (or whatever). (c:\c642016). Check that the ACME cross assembler has also been included in your directory. You will need to call a path to compile and run the source code.

Extract the rest of the files as normal. Install DOSBOX, because you will need it.

BACK TO TOP


1B. SETTING UP AND TESTING THE SOURCE

Boot up Relaunch64. Load up the SCROLLER files in C642016\C64 (which you extracted into your directory) into the Relaunch64. You should see the source code in the text editor.. For the time being just open ScrollEntry.a and ScrollerDataMacro.a into Relaunch64. Don't do anything yet, because we want to do a TEST build of the source code to make sure the default example game is working in the source code.

Now for the practical part. We shall test one of the example sources that has been included in the archive.  You can see that many of the BIN (Binary files) have been commented out. A lot of those files were test files, but have not been included in the source code. We shall leave everything for the time being and just setup a test run of the first example game. In Relaunch64, select the following option in the menu:

Options ... Preferences ...

Click on the tab 'Compile and Run scripts'. Click on the NEW SCRIPT button and type in the following (Or copy+paste) compile command:

del Scroller.prg
c:\c642016\c64\acme.exe -v3 --msvc ScrollEntry.a
if not exist Scroller.prg goto error
echo Compressing with Exomizer
c:\exomizer\win32\exomizer.exe sfx $0400 scroller.prg -o scroller.prg -n -s "lda #$0b sta $d011" -f "lda #$1b sta $d011" -q

if not exist Scroller.prg goto error

C:\WinVICE-2.3-x86\x64sc.exe scroller.prg
goto end
:error
echo Scroller.prg not created!

:end

MAKE SURE THE PATH NAMES ARE CORRECT, or RENAME the paths. Name the script as SEUCK REDUX .

Click on UPDATE SCRIPT. Then exit the script editor

Now we are ready to compile and run the example game. PRESS F5. The commands on the RIGHT will show the status of compiling. Should there be no ERRORS, WinVice will boot up and load up the assembled and compressed program. You can have a play at the game if you want to, but what about enhancing your own SEUCK game?... Simple.

BACK TO TOP



1C. IMPORTING YOUR OWN GAME INTO THE SOURCE CODE:

Now you have tested the SEUCK Redux engine. It is time to import your own SEUCK game data into the source code. In order to be able to do this, you need DOSBOX, 64copy  or any other PC tool to help transfer a SEUCK ALL DATA file from a D64 image into the SEUCK Redux 'SEUCK' directory.

- Boot up DOSBOX (Or whatever tool you are using)
- Mount the HDD directory to any drive number for example

z:\>mount c: c:\

- Now enter c:\ (or whichever drive you have mounted)

- Move to the directory where 64copy is. On my HDD I use c:\

c:/>cd\64copy

Then type in ....

64copy

64Copy should then run and display two windows. You can use the TAB key on the keyboard to switch between windows.  At the window on the right. Open the C64/SEUCK directory. Then using the TAB key, switch back to the window on the left, open the directory where your .D64 with your saved SEUCK data is placed. Select the D64 using ENTER and then highlight the SEUCK data file. Press F5 to copy the file to the C64 Directory. A dialogue box will appear. Select to copy as .P00, since this will be the format you need for your SEUCK work files.. Once copied. You won't need to use Dosbox again for a while. So type EXIT twice to end the application.

Now that has been done. What you want to do now is test your game in SEUCK Redux. Go to the file ScrollerDataMacro.asm and look for the UNCOMMENTED (!bin command without an ; next to it), and rename the file with the 8 character filename which 64copy converted into the SEUCK directory. For example... Rename GAME1__I.P00 to the name of your game.

Once you have done that. Click on the save tab on Relaunch64 and then press F5 to compile and test the code. If your game is standard SEUCK, then background should be in tact otherwise if the game is SIDEWAYS SEUCK, then you'll notice your map will look completely garbled up. That's probably because in ScrollEntry.a you didn't uncomment Scroller_isHorizontal=1. So make sure you uncomment Scroller_IsHorizontal=1 in ScrollEntry.a if using Sideways SEUCK. Otherwise comment it out if using standard SEUCK.

BACK TO TOP




2. ADDING POWER UPS

When creating games in the SEUCK Redux environment it is possible to generate different types of power ups for the player. It is also possible to alter the animation frame of the player, its bullet and other bits. Zap Fight 2, featured in Shoot Em Up Destruction Set #4 is one example which uses the awesome power up feature. The event occurs every time a player picks up a specified object value (original object value set in SEUCK). It is possible to create as many power ups as you probably can. In this chapter we look at identifying the collectible enemy object picked up. Then later on give the player player power ups, which involve, speed, amount of bullets, invincibility, and awarding extra lives. 

In order to give the player specific power ups. The AnimationType should be read

        lda AnimationType,x
        cmp #OBJECT_TYPE
        bne .NotPickup
        jsr .Effect
        jmp .ExitPowerUpTest

If you refer to the original SEUCK editor, the source is trying to test the animation type object, to see which object has been killed by the player or bullet. Object 22, represents ACTUAL ENEMY 1 and Object 57 represents ACTUAL ENEMY 36. Refer to the OBJECT NUMBER (not Actual Enemy value. Otherwise that WONT work.). For this example we shall refer to Actual Enemy 22, (Object 43) from Nuclear Strike Force. The player collects an airship power up, in order to gain better firing abilities.

NOTE: You will need your original SEUCK work file to look at in order work out the enhancements.





2A. A QUICK EXAMPLE (BORDER CHANGE):

In AnimationEngine.a, Look for the label .makeItDead (Before !IF DEF LOTD). Add the following command. This will test whether or not ENEMY 22 (Object 43)  has been killed. If it has, then a border will change colour. If not then no effect will take place. (This is referred to Nuclear Strike Force by the Way).

.makeItDead
        lda AnimationType,x    ;Check actual object
        cmp #22            ;Actual Enemy 1
        bne .NotPowerUp
        jsr AwardPowerUp
        jmp .makeItDeadEnd
.NotPowerUp
.makeItDeadEnd

BACK TO TOP



2B. TESTING MORE THAN ONE ENEMY KILLED

It is possible to EXPAND the enemy check command. Say, if you had a multiple number of enemies to give power ups you can simply expand the routine above.Say for example enemy 2 and enemy 3 are different sprites to give power ups to the player. The command can be modified like this:

.makeItDead  lda AnimationType,x    ;Check actual object
             cmp #22            ;Actual enemy 1???
             bne .NotPowerUp1
             jsr AwardPowerUp
             jmp .makeItDeadEnd

.NotPowerUp1 cmp #23            ;Actual enemy 2???
             bne .NotPowerUp2
             jsr AwardPowerUp2
             jmp .makeItDeadEnd

.NotPowerUp2 cmp #24            ;Actual enemy 3???
             bne .NotPowerUp3
             jsr AwardPowerUp3
             jmp .makeItDeadEnd
.NotPowerUp3
              
.makeitDeadEnd

Now look for the command .charThatHit, and type in the following subroutine. This will make the border red.

.charThatHit    !byte 0

AwardPowerUp    lda #2            ;Colour RED
                sta $d020        ;Border colour
        rts

Now what if you wanted to actually set a power up to allow the player arm itself with faster bullets and change the animation frame for player 1?.

You'll need to create an 18 byte table based on sprite values for each player. Before you can generate the sprite value table in SEUCK's object editor. You should look at the sprite order table.  If your player type uses directional frames. To get the correct  frame order, set the Animation Type in SEUCK to something else other than DirectionalHold. (DON'T SAVE YOUR GAME IN SEUCK AFTERWARDS ...)



Look at the two images above. The first example indicates the player in directional/directional hold. If you used the sequences from the directional/directional hold table to transform your ship with different sprites. You will end up with some animation errors. Whereas the PROPER way to make an 18 byte table is to temporarily change the Directional/Directional hold type to the one before it. That will then display an 18 sprite table in the correct order of sequence. This trick is very handy for transforming the player, bullet or whatever you like to transform.

In AnimationEngine.a Underneath The AwardPowerUp subroutine, underneath RTS add a bullet power up table to the source. (DON'T COPY THIS TABLE BELOW, USE THE CORRECT VALUES OF SPRITES IN your SEUCK project which you would like to use as bullets for power ups). For this example I'm turning the player's bullet into a black bomb.




Bullet_Power_Up_Table:   
            !byte 035,035,035,035,035,035

            !byte 035,035,035,035,035,035
            !byte 035,035,035,035,035,035

Now change the subroutine AwardPowerUp to read the table and store it to all 18 frames in the actual sprite object.

AwardPowerUp     ldy #$00                            ;USE Y' loop NEVER USE X LOOP, else it will mess up the animation
.PowFrameLoop    lda Bullet_Power_Up_Table,y        ;Read Bullet_PowerUpTable
                 sta ObjectAnimations+($14*AnimationType_Player1Bullet),y     ;Store to Object frames for - Player 1's bullet
                 iny
                 cpy #18
                 bne .PowFrameLoop
                rts

BACK TO TOP


2C. BULLET SPEED

Assuming you want to increase the speed of the player's bullet this can be altered by setting up a value of the two properties.
           
                 Player1Properties+PlayerOffset_BulletSpeed
                 Player1Information+PlayerGameOffset_FireSpeedNeg
                                                                                       or
                 Player2Properties+PlayerOffset_BulletSpeed
                 Player2Information+PlayerGameOffset_FireSpeedNeg

In order to set a new bullet speed for the player, a POSITIVE and NEGATIVE value needs to be set. If the player is shooting DOWNWARDS or RIGHT. Velocity values are POSITIVE. UPWARDS or LEFT give NEGATIVE values. So Let's say you wanted to fire a bullet at a speed of 4. We set the bullet speed like  so:

                 lda #4 ;Give positive value for player bullet speed
                 sta Player1Properties+PlayerOffset_BulletSpeed
            ... or if you want to include player 2 with this ...
                 sta Player2Properties+PlayerOffset_BulletSpeed

                 lda #-4 ;Give negative value for player bullet speed
                 sta Player1Information+PlayerGameOffset_FireSpeedNeg
            ... or if you want to include player 2 with this ...
                 sta Player2Information+PlayerGameOffset_FireSpeedNeg

Now let's add it to the power up subroutine - Along with the frame change ...


AwardPowerUp     ldy #$00                    ;USE Y' loop NEVER USE X LOOP, else it will mess up the animation
.PowFrameLoop    lda Bullet_Power_Up_Table,y ;Read Bullet_PowerUpTable
                 sta ObjectAnimations+($14*AnimationType_Player1Bullet),y  ;Store to Object frames for - Player 1's bullet
                 iny
                 cpy #18
                 bne .PowFrameLoop
           
                 lda #4 ;Set speed of player 1 bullet (Positive)
                 sta Player1Properties+PlayerOffset_BulletSpeed

                 lda #-4 ;Set speed of player 1 bullet (Negative)
                 sta Player1Information+PlayerGameOffset_FireSpeedNeg
                 rts


BACK TO TOP


2D. CHANGING THE PLAYER'S OBJECT

You may have already noticed about the bullet object being changed to a  different frame. It is also possible to read a table and change the animation of the player as well. Yet again, by generating another 18 byte frame table and storing it to the player can be done.

Just for fun, I will be transforming the player's jet into one of the enemy tanks. Underneath the 18 byte table Bullet_Power_Up_Table, add another 18 byte table for the PLAYER anim.  




Player_Power_Up_Table
            !byte 085,081,082,078,078,078
            !byte 082,081,085,084,080,083
            !byte 079,079,083,080,035,085

The object animation type for storing 18 sprites to the player is

ObjectAnimations+($14*AnimationType_Player1)
         or
ObjectAnimations+($14*AnimationType_Player2)

Now let's add this into the AwardPowerUp subroutine


AwardPowerUp     ldy #$00                                     ;USE Y' loop NEVER USE X LOOP, else it will mess up the animation
.PowFrameLoop    lda Bullet_Power_Up_Table,y                          ;Read Bullet_Power_Up_Table
                 sta ObjectAnimations+($14*AnimationType_Player1Bullet),y     ;Store to Object frames for - Player 1's bullet
                 lda Player_Power_Up_Table,y                          ;Read Player_Power_Up_Table
                 sta ObjectAnimations+($14*AnimationType_Player1),y   ;Store to Object frames for - Player 2
                 iny
                 cpy #18
                 bne .PowFrameLoop
           
                 lda #4 ;Set speed of player 1 bullet (Positive)
                 sta Player1Properties+PlayerOffset_BulletSpeed

                 lda #-4 ;Set speed of player 1 bullet (Negative)
                 sta Player1Information+PlayerGameOffset_FireSpeedNeg
                 rts

BACK TO TOP

           
2E. SETTING DEFAULTS

Although we now have power ups setup into the game, itself. There is a slight snag involved with this. The feature stays in the game. Should you wish to start a new game, the power ups are still stored in the game's memory. In order to remove the power ups and restore the player or bullet. A default subroutine should be created. A table that defaults the player and bullet would need to be created.

Default_Player
            !byte 001,001,001,001,001,001
            !byte 001,001,001,001,001,001
            !byte 001,001,001,001,001,001

Default_Player_Bullet

            !byte 003,003,003,003,003,003
            !byte 003,003,003,003,003,003
            !byte 003,003,003,003,003,003

Now let's create a subroutine that will default everything underneath RTS in AwardPowerUp

DefaultPlayerSettings
            ldy #$00
DefaultPlayerLoop    lda Default_Player,y
            sta ObjectAnimations+($14*AnimationType_Player1),y
            ... can also do this for player 2 if 2 player game ...
            lda Default_Player_Bullet,y
            sta ObjectAnimations+($14*AnimationType_Player1Bullet),y
            iny
            cpy #18
            bne DefaultPlayerLoop
            lda #2 ;Bullet speed 2
            sta Player1Properties+PlayerOffsetBulletSpeed
            lda #-2
            sta Player1Information+PlayerGameOffsetFireSpeedNeg
            rts

As you know, this subroutine will not work yet. In order to fix this issue. We need to make a JSR call, to the subroutine. Both of these effects should occur in player settings (Should you wish the player to lose all power ups when it dies). Also at a start of a brand new game, the default settings should be in place.

In the following assembly source files

PlayerControl.a       
       
Look for the command:

dec Player1Information+PlayerGameOffset_Lives

Before that command, enter

            jsr DefaultPlayerSettings

Now in the source code ScrollMain.a look for the command jsr TitleScreenWaitForOffScreenFromRaster add underneath the } underneath that prompt

                               jsr DefaultPlayerSettings

Save all of your changes and then test run the compiled program. You now have a game with one power up and it gets lost after a new game has started, or a life has been lost.

BACK TO TOP


2F. PROGRESSIVE POWER UPS

It is possible to make progressive power ups in order to improve on the player's capabilities. A counter has to be set and the counter value should be checked. If you reach the last check in the counter the cycle could either reset or something different could occur. Let me take Zap Fight 2 for example.



The player has to pick up stars in order to gain various power ups. Those power ups can either change the shape of the player ship or increase the firing rate of the player. There was also a special feature where the player could have a drone power up. That drone was in fact player 2. The second player was set to be invincible and was controlled using the linked players / twin mode option in ScrollEntry.a

In order to create a power up counter you would need to create a single byte.

So, after RTS in DefaultPlayerSettings, in AnimationEngine.a add a single byte to make a power up counter. Basically set it to 0.

PowerUpCounter    !byte 0

Now in the subroutine AwardPowerUp, add the following code

AwardPowerUp
            inc PowerUpCounter ;Increment value of power up counter

            lda PowerUpCounter
            cmp #1           ;If PowerUpCounter = 1 ... Power up 1 set
            bne NotPowerUp1
            jmp AwardPowerUp1

NotPowerUp1 cmp #2
            bne NotPowerUp2
            jmp AwardPowerUp2

NotPowerUp2 cmp #3
            bne NotPowerUp3
            jmp AwardPowerUp3

NotPowerUp3 cmp #4
            bne NotPowerUp4
            jmp AwardPowerUp4

NotPowerUp4 cmp #5
            bne NotFinalPowerUp
            jmp AwardPowerUp5

NotFinalPowerUp      
             rts


Let's have a little play with BASIC power ups. - Boost the player's speed, fire rate, amount of bullets, etc. Make the final power up an extra life.

Before making the power ups, let's make a default setup which is linked to the player settings.

In AnimationEngine.a where we created DefaultPlayerSettings setup up the default speed for the play, the bullet speed (positive and negative) and also amount of bullets. Set up the code to set the default speed of your game, referring to the SEUCK editor. I have decided to base this setup on Zap Fight 2.

DefaultPlayerSettings

            lda #0
            sta PowerUpCounter ;Reset power up counter

            lda #$06
            sta Player1Properties+PlayerOffset_BulletSpeed ;Positive bullet speed for P1
            lda #-6
            sta Player1Information+PlayerGameOffset_FireSpeedNeg ;Negative bullet speed for P1

            lda #0 ;ALTHOUGH 0 ... That will shoot one bullet at a time
            sta Player1Properties+PlayerOffset_NumBullets

            lda #2
            sta Player1Properties+PlayerOffset_Speed

           
            ldy #$00
DefaultPlayerLoop    lda Default_Player,y
            sta ObjectAnimations+($14*AnimationType_Player1),y
            ... can also do this for player 2 if 2 player game ...
            lda Default_Player_Bullet,y
            sta ObjectAnimations+($14*AnimationType_Player1Bullet),y
            iny
            cpy #18
            bne DefaultPlayerLoop
            rts

Now let's make some new power ups. Underneath the rts by NotFinalPowerUp add the following:

;POWER UP 1 - Set a new speed to the player
AwardPowerUp1        lda #3
            sta Player1Properties+PlayerOffset_Speed
            rts

;POWER UP 2 - Set bullet count to 3 (3 bullets firing), also change
;the bullet firing animation
AwardPowerUp2        lda #2
            sta Player1Properties+PlayerOffSet_NumBullets
           
            ldy #$00
changeanim  lda Power_Up_Bullet,y
            sta ObjectAnimations+($14*AnimationType_Player1Bullet),y
            lda Power_Up_Player,y
            sta ObjectAnimations+($14*AnimationType_Player1),y
            iny
            cpy #18
            bne changeaanim
            rts

;POWER UP 3 - Increase bullet speed to its max

AwardPowerUp3
            lda #9

            sta Player1Properties+PlayerOffset_BulletSpeed
            lda #-9 ;If directional fire is in the game.
            sta Player1Information+PlayerGameOffset_FireSpeedNeg
            rts

;POWER UP 4 - Temporary invincibility

AwardPowerUp4       
            lda #255 ;Set invincibility counter

            sta Player1Information+PlayerGameOffset_Invulnerable
            rts

;POWER UP 5 - Give out an extra life

AwardPowerUp5
            lda #0 ;Reset Power up counter

            sta PowerUpCounter
            inc Player1Information+PlayerGameOffset_Lives
            rts

2G. OTHER PLAYER PROPERTIES + INFORMATION

This is more of a theory session than a practical, but it gives your more examples of the player settings, which could be triggered to be enabled or disabled or configured. Here is a brief description for each feature, which could be triggered/configured in your SEUCK game.

This can refer to one or BOTH players

Player1Information+PlayerGameOffset_[command]
or
Player2Information+PlayerGameOffset_[command]

... for example

Player1Information+PlayerGameOffset_Lives

Lives ;Amount of lives for player 1 (or player 2, if changed to Player2Information).
Invulnerable ;Invincibility counter.
TargetVelX ;Target X Velocity
TargetVelY ;Target Y Velocity
FireSpeedNeg ;Negative directional fire

Player1Properties+PlayerOffset_[command]
or
Player2Properties+PlayerOffset_[command]

... for example

Player1Properties+PlayerOffset_BulletSpeed

BulletSpeed ;Positive bullet speed
DieOrStop ;If hit background, should the player die or stop (0 = stop, 1 = die)
Character_Collision ;Which char and higher should the player collide into (0-254).
Directional ;Directional fire enabled/disabled (0 = Disabled, 1 = Enabled)

ObjectAnimations+(value*AnimationType_[Command])

Where value = type of value of object (Could range from animation speed, anim type, etc)

ObjectAnimations+($14*AnimationType_Player1) - 18 Sprite frame table for player 2
ObjectAnimations+($14*AnimationType_Player2) - 18 Sprite frame table for player 2
ObjectAnimations+($14*AnimationType_Player1Bullet) - 18 Sprite frame table for player 1 bullet
ObjectAnimations+($14*AnimationType_Player2Bullet) - 18 Sprite frame table for player 2 bullet

AnimationSpriteColour+(value)

Colour of an actual sprite object

BACK TO TOP



3. ENEMY AIM FUNCTION



3A Enemy AIM firing

SEUCK games have always been the same, and made enemies fire the way you wanted to make them fire. Enemies could either shoot, up, down, left, right, 4 way horizontal and vertical, 4 way diagonal and random and the same direction an enemy was moving. Every single SEUCK game used that function. Now wouldn't things be even MORE interesting if enemies could actually aim for player before firing?. SEUCK Redux versions of Tau Zero, Tau Omega, Nuclear Strike Force  and Zap Fight 2 all used this function. Now guess what we are going to do ... EXACTLY THAT!

Before you can get enemies to AIM, you will need to take a look at the ENEMY bits of the enemy object you would like to AIM. For my example, I have chosen the red enemy tank which rotates its turrets in Nuclear Strike Force. Object 25 - Actual enemy 03. To detect which enemy can use the aim function, we can simply use the COMPARE method yet again, as we did for detecting power ups.



In ScrollEntry.a, look up ;EnemyAimTest = 1, and remove the ; beside the command to enable it. Now in AnimationEngine.a look up .smAnimType underneath !ifdef EnemyAimTest { and type in the following command:

!ifdef EnemyAimTest {
.smAnimType             lda #0    ;Self modified
                        cmp #25   ;Is object 25 (Actual Enemy 03) firing
                        bne .notDoAimedFire
                        jmp .doAimedFire
.notDoAimedFire
}

Now if you test this. The red tanks will AIM for player 1 instead of fire random shots.

3B. Enabling more than one enemy type use EnemyAimTest

What if you want more enemies to use the AIM function. Simply browse through your SEUCK work file, pick out the enemy objects, and expand the code. Let's do the same trick for enemies 4,5 and 6. Update the source like this:

!ifdef EnemyAimTest {
.smAnimType            lda #0     ;Self modified
                       cmp #25    ;Is object 25 firing
                       bne .checkNextObject1
                       jmp .doAimedFire    ;Allow enemy to AIM for the player's position
.checkNextObject1      cmp #26    ;Is object 26 firing
                       bne .checkNextObject2
                       jmp .doAimedFire    ;Allow enemy to AIM for the player's position
.checkNextObject2      cmp #27    ;Is object 27 firing
                       bne .notDoAAimedFire
                       jmp .doAimedFire    ;Allow enemy to AIM for the player's position
.notDoAimedFire        ;Ignore the rest of the enemy object types
}

You don't always need to choose enemies that fire randomly to AIM for the player. You can choose any enemy you like to perform this task.

That's all you need to know for the enemy aiming function.

BACK TO TOP



                       
4. BACKGROUND ANIMATION

This chapter is a very small feature on in game background animation, and using it in SEUCK Redux. As you noticed in the past, most of my SEUCK Redux enhanced games use the background animation trick. This tutorila has two different types of background animation tricks. These are as follows:

1. Parallax Background add on feature

This is a built in function, which comes with SEUCK Redux. The Parallax Background scroller is an example 5x5 block scroller, which has additional code implemented into the source. A guide to using this feature has been added to this tutorial. (Only works on Standard vertical scrolling code).

BACK TO TOP


2. Single Character animation

This is probably the most easiest method for making a single char constantly scroll and wrap. A feature which I used a lot in and outside SEUCK Redux. It is also possible to animate charsets to change shape as well.

BACK TO TOP



4A. The Parallax Background Add On

Before you read on. Please be aware that this extension will only work on vertical scrolling SEUCK games. The parallax feature scrolls 3 layers together. Here is how the demo scroller looks with all characters/blocks put together.




In order to be able to use this feature. The SEUCK background editor needs to be used TWICE. In order to understand the parallax scrolling, take a look at the example of the SEUCK background editor below. Copy the data files from the P00 into your .D64 (Using 64copy) and then load up SEUCK in order to examine (and maybe edit them). Load in SEUCK, then load the ALL DATA file of the PARALAXTEST file and examine the background chars (in the background editor). Then load the ALL DATA file of the PARAXBLOCKS file and examine the first set of chosen chars for that also. 
The two screen shots below show you the first set of chars which form the background scrolling and the parallax effect inside the blocks. The parallax scroll consists of a charset overriding another character set, over the background to give a visual effect. This feature is most suitable for games such as futuristic blasters.


Left: The rows of chars that form the parallax effect inside the map

Right: The rows of chars that form the chars that should go OVER the parallax. The first 25 chars (000 - 024) indicate where the each layer of the 25 parallax chars should be placed. Basically, create 2 blocks for the parallax scroll.

In order to be able to test/use the parallax scroll. In ScrollerDataMacro.a uncomment the Parallax test binary files (Remove ; beside the command) and rename the two test files with your very own creation. Where one is your main scroller, and the other is your parallax block scroller. Files must have been saved as ALL DATA. Then in ScrollEntry.a uncomment Paralax_Enable = 1. This will then enable the extended code that can perform the parallax scrolling.

Should this feature not work the way you want to. It is worth playing around with the SEUCK until you get what you wish to have. Remember to keep chars 25 - 96 of your actual map reserved as blank chars in your test scroll.

BACK TO TOP



4B. The Single Char Animation

Many games I wrote using SEUCK Redux has at least single char animation. This may vary to scrolling chars, to form waterfalls or flowing water, lava, etc or scrolling voids. It is possible to scroll your chars any direction.

SEUCK's background character set in SEUCK Redux is stored at $c000-$c7ff. Each character consists of 8 bytes. In order to get a scrolling effect, you roll the 8 bytes forwards or backwards (for up/down), or you can scroll the chars left, and right by rotating the value of the whole charset to the left or rotating the value of the whole charset to the right. At ScrollMain.a look for SFXPlay or MusicPlayerPlay and before the comment:


!ifdef DisableSound {} else {
!ifdef Scroller_MultiDirection {
    jsr MusicPlayerPlay
} else {
!ifdef Scroller_PlaySoundEffectsDuringGame {
... rest of program

Add a new subroutine, which is:

                     jsr AnimateBackground

Before we can actually scroll a single character, we would need to work out the value of the charset. Up / Down is basically picking the first or last byte of the chosen character, place it into a temp byte, then perform a loop which will push/pull each byte to the next byte. 

                    8*n+$c000 ;Where n = the block number

Then store a temp byte into the first / last row of the character set. Say for example you want to scroll char 073, a subroutine looks like this:

Scrolling chars up:             

doCharAnim1   lda 8*73+$c000,x
              sta tempbyte
              ldx #$00
scrollCharUp  lda 8*73+$c000+1,x
              sta 8*73+$c000+0,x
              inx
              cpx #$08
              bne scrollCharUp
              lda tempbyte
              sta 8*73+$c000+7
              rts

tempbyte      !byte 0

Now what if you wanted to scroll chars down. Well, we reverse the process and carry the bytes forwards, rather than backwards. Here's how to do it:

Scrolling chars down:

doCharAnim2    lda 8*73+$c007
               sta tempbyte2
               ldx #$07
scrollCharDown
               lda 8*73+$c000-1,x
               sta 8*73+$c000,x
               dex
               bne scrollCharDown
               lda tempbyte2
               sta 8*73+$c000
               rts

tempbyte2      !byte 0
What about left or right scrolling? Well ASL, LSR ROL and ROR are pretty much helpful for those particular features. There's no need to make tempbytes when scrolling left or right.

Scrolling chars left:

doCharAnim3   ldx #$00
scrollCharLeft
              lda 8*73+$c000,x        ;Rotate chars to the left
              asl                     ;8 times in the loop
              rol 8*73+$c000,x        ;will scroll a single char
              asl                     
              rol 8*73+$c000,x
              inx
              cpx #8
              bne scrollCharLeft
              rts

... and for scrolling chars to the right - we do the opposite ...


Scrolling chars right:

doCharAnim4   ldx #$00
scrollCharRight
              lda 8*73+$c000,x        ;Rotate chars to the right
              lsr                     ;8 times in the loop
              ror 8*73+$c000,x        ;will scroll a single char
              asl                     
              rol 8*73+$c000,x
              inx
              cpx #8
              bne scrollCharRight
              rts


Finally ... If you tried one of these four features, you will notice that the charset animation is scrolling too fast. In order to slow it down, a timer/delay is needed to be made. So, let's go back to the upward scrolling subroutine, and add a time to the scroll.

AnimateBackground
                lda BGRDelay
                cmp #$02 ;Changeable speed for the effect
                beq doCharAnim
                inc BGRDelay
                rts

doCharAnim      lda #0
                sta BGRDelay
                lda 8*74+$c000
                sta tempbyte
                ldx #$00
ScrollCharsUp   lda 73*8+$c000+1,x
                sta 73*8+$c000,x
                inx
                cpx #8
                bne ScrollCharsUp
                lda tempbyte
                sta 73*8+$c000+7
                rts

BGRDelay        !byte 0

That's it for character set animation.

BACK TO TOP



5. MUSIC AND SOUND EFFECTS

SEUCK Redux has support for allowing you to play in game music or sound effects. There are for different methods which SEUCK Redux can use, where it comes to playing music, or sound effects. These are:

Title screen with music, in game sound effects only
Title screen with music, in game music
Title screen with music, in game music with sound effects
Title screen without music, in game sound effects.

The commands in ScrollEntry.a look something like this:

Scroller_PlaySoundEffectsDuringGame = 1


The command above allows your game to play standard SEUCK sound effects. however, with an extension below, it also allows you to play IN GAME MUSIC and SOUND EFFECTS. The extension looks like this:

Scroller_PlaySoundMusicAndSoundEffectsDuringGame = 1

In order to play sound effects as well as music. You should use Martin Piper's 'MusicStudio V2.2' and allow SFX support. Although when I created enhancements for Hover Raider, I created my very own SFX player and linked the player to the code, since music was composed using a different editor.

Scroller_NoMusic = 1

This will switch off all music players, and not assemble any in memory. Should the command Scroller_PlaySoundEffectsDuringGame =1 also be disabled, this will crash the system. So be careful.

BACK TO TOP



5A. Music Players, Format and Memory

SEUCK Redux allows any type of music player, which fits in memory range. Music must be relocated to $8000. Most C64 musicians nowadays likes to use the Goat Tracker, or Cheesecutter, due to the powerful tunes that can be created with the music editor. Memory for music needs to be at $8000-$9200. If the music data goes OVER that area, it could corrupt some of the background graphics block data positions. The SEUCK Redux can also support tunes made with Future Composr, Dutch USA Music Assembler, JCH and DMC players. To add your tune into the source, look for the "MusicAndSFX.PRG" in ScrollerData.a and rename it with your own file.

BACK TO TOP



5B. Setting up Init and Play of Custom Music Players:

If you are using GoatTracker, MusicStudioV2.2 Cheesecutter, DMC, or anything like that in particular. You won't need to setup the init and play address, as it is already set up for you in the source code. However should you wish to change the INIT / PLAY address. You can look for MusicPlayerInit and MusicPlayerPlay in ScrollerData.a and change the addresses you wish the music to init and play at.

Future Composer:                     INIT $8000 / PLAY $8006
USA Music Aseembler/Voicetracker:    INIT $8048 / PLAY $8021

BACK TO TOP



5C. Playing a different tune for in game music

If you disable in game sound effects feature, and wish to have just in game music. When you run your game, and enable in game music. You'll discover that it plays the title music by default. With C64 games. It is always good to have an in game tune, as well as a title tune. Assuming that in MusicStudio or any other music player. You created two different tunes on the same file. (Track 0 and Track 1). You want Track 0 as the title screen, and wish to play Track 1 as in game music. All you will need to do is add one additional command in ScrollMain.a.

In ScrollMain.a look for the command: MusicPlayerInit and before MusicPlayerInit, change it to:

                        lda #$01 ;Play track 1
                        jsr MusicPlayerInit

Test run the source and you'll get track 1 playing in your game.

BACK TO TOP



5D. Playing in game Music and Sound effects

There is a feature in SEUCK Redux, which allows you to play in game music and also sound effects as well. However this feature doesn't always work right, due to the sound/instrument limitations. You need to use MusicStudio V2.2 to not only compose your music, but also create instruments to use as the sound effects. Two commands need to be enabled in ScrollEntry.a In order to be able to play sound effects with music. They are as follows:

Scroller_PlaySoundEffectsDuringGame = 1

Scroller_PlaySoundMusicAndSoundEffectsDuringGame = 1
                           
Also you will need to take a look at SFXWithMusic.a and edit the table which will select the chosen instruments that will play as sound effects. Also the voice pitch table. The SFX table (for playing the instruments) look something like this. In the example below, while a normal tune is playing in the background. Instruments 2, 3, 4, and 5 are used as in game sound effects. Tunes 2 and 3 are also used as the drum instrument, and voices 4 and 5 represent the lead instruments. It is up to you to work out your own instruments and implement those into the tables below.

; A lookup table that converts SEUCK SFX number to the music player envelope number
; There are 24 SEUCK sound effects
.SEUCKToMusicSFX
    !by 2 , 3 , 4 , 5 , 5 , 4 , 3 , 2
    !by 2 , 3 , 4 , 5 , 5 , 4 , 3 , 2
    !by 2 , 3 , 4 , 5 , 5 , 4 , 3 , 2

; A lookup table to allow each sound effect to have a different note
.SEUCKToMusicSFXNote
    !by 48, 50, 32, 16, 32, 48, 52, 40
    !by 48, 50, 32, 16, 32, 48, 52, 40
    !by 48, 50, 32, 16, 32, 48, 52, 40

It is possible to NOT use the 
Scroller_PlaySoundMusicAndSoundEffectsDuringGame and customize the ScrollMain to play in game music, and your very own sound effects player (Like I did for Hover Raider). Simply add after jsr MusicPlayerPlay a JSR CustomFXPlayerPlay or whatever you would like it to be.

BACK TO TOP



6. DATA GROWTH AND HOW TO USE IT

If you wanted to really push your game, which you made using SEUCK. Not only should additional code be created, but you should use external DATA in order to enhance your production even more. SEUCK Redux completely strips out the SEUCK Editor, and reserves memory for additional data an code. For example, you'd want an external charset, or sprites data for a custom score panel. Or maybe, a few charsets and matrix data for a logo for your front end. SEUCK Redux leaves plenty of room for expansion. All you need to do is program a new front end or whatever that supports the data / additional that is placed in memory. One example which uses the DATA GROWTH is Hover Raider.


An external charset, and screen memory is reserved for the char based score panel (Where the command in ScrollEntry.a disables Scroller_FullScreen=1, by commenting it out). Also the external data growth was used for scroll text. Areas which may be allowed at the beginning of data growth should not overlap $8000. Extended data and code can also be added between $f000-$ff40. If you required to transfer charset data to make the score panel. In order to get a working panel, you will need to generate your own code and store it to screen position memory.

Okay. That is a bit of explanation about DATA GROWTH, but what about how to use it all?

Let us say that you wanted to edit the existing code for the SEUCK front end and you wish to make something which stands out more. You can add external data and code in memory. There's plenty of space for certain data, but impossible to fit a bitmap logo/picture in to the source, due to the code. Logos are best stored in 3-coloured Font and Screen format. The same goes for sprite data, etc for a title screen. In order to get your custom font and logo in place on to the title screen. You would need to label the binary file in ScrollerMusicData.a for example. Build a logo, and combine a charset with the logo, and display
the logo's screen:

SOURCE: ScrollerMusicData.a

LogoCharset        !bin "mychar.prg",,2

TextCharset        !bin "textcharset",,2
LogoMatrix         !bin "myscreen.prg",,2

SOURCE: TitleScreen.a

;Relocate logo charset to $0800-$0bff, and TextCharset to $0c00,$0fff

Look up the subroutine which copies the SEUCK title screen charset, and replace it with:

;This will fill memory with the charset data.

                ldx #$00
RelocFont       lda LogoCharset,x
                sta $0800,x
                lda LogoCharset+$100,x
                sta $0900,x
                lda LogoCharset+$200,x
                sta $0a00,x
                lda LogoCharset+$300,x
                sta $0b00,x
                    
                lda TextCharset,x
                sta $0c00,x
                lda TextCharset+$100,x
                sta $0d00,x
                lda TextCharset+$200,x
                sta $0e00,x
                lda TextCharset+$300,x
                sta $0f00,x
                inx
                bne RelocFont

Displaying the logo matrix row by row is simply:

                ldx #$00
DrawMatrix      lda LogoMatrix,x
                sta $0400,x
                lda LogoMatrix+1*40,x
                sta $0400+1*40,x
                lda ... next line, etc
                sta ... next screen line, etc
                inx
                cpx #$28 ;40 chars a row
                bne DrawMatrix


SEUCK Games always had the same old score and lives panel, which is quite boring. It is possible to use custom sprites to make a custom score panel (This has been mentioned in a later chapter). We can use the same method to relocate other bits of data to the BANK 3 memory, when we need to use it. Then implement some code into it. (SEE Chapter 8 on score panels).

It is possible to save memory by simply just importing the title screen logo matrix and copy the ORIGINAL font from your original SEUCK title screen presentation and move it. However code would need to be tweaked in order to display either the charset or the title screen logo correctly.
       

BACK TO TOP



7. ADDITIONAL SEUCK REDUX COMMANDS / FEATURES

There have been many good additional features implemented into SEUCK Redux in order to make the games stand out more. Take a look at ScrollEntry.a to see what they are and look like. I'll tell you a few examples and what these actually do. Of course if you wanted to use those features you may have to tweak them in your game, to make it the way you want it to be. The commands are as follows:

Scroller_FullScreen = 1

This command makes full use of the full border. Like SEUCK Does. The score panel consists of sprites, and can also be edited with your own code in the SetupIRQs.a and ScrollMain.a code. We do have examples. When disabled the code will not use the full screen, but instead, will use screen char, for a char based score panel. Chapter 8 will tell you more about this feature.

Scroller_LevelSkipDemoCode = 1

A special feature, which can skip levels, should up on a joystick in port 1 be pushed once. This feature can be edited to create clever tricks such as flip screen. Say you were writing a vertical scrolling space shoot 'em up and you wanted to create objects to teleported the player to another world, or loop instantly. This feature is very handy for exactly THAT. Of course the code would need to be edited to change joystick push up to object detection.

Scroller_UseDemoScorePanel = 1

This is an extension which uses Martin's example char score panel. Without it, the status screen will be blank. Disable full border option. It will be up to you to design your own score panel, and implement some code to get it working. Chapter 8 will show you how it can be done :)



Scroller_NeedFullColourScroll = 1

Allows the screen to use full colour scroll code. If this is not enabled then colour scheme will always be the same.

Scroller_IsHorizontal = 1

Allows Sideways SEUCK scrolling engine to be used. If you imported Sideways SEUCK ALL DATA files into SEUCK Redux and not enable Scroller_IsHorizontal. The code will think your game is vertical scrolling and will mess the map, and scroll upwards instead of to the right.

Scroller_LOTD = 1

Gives you extended code for Legion of the Damned. A game which was written back when SEUCK Redux source first came out. The scrolling is set to horizontal, and also gives the players the ability to cast spells (smart bomb) on the enemies when keys 'S' or 'W' are pressed - every time the player collects a bottle.



Scroller_PlaySoundEffectsDuringGame = 1

Allows to play SEUCK's default in game sound effects. If disabled, will only play the title music (Unless you set the in game music to init after the title screen, before music plays in the game).

Scroller_PlaySoundMusicAndSoundEffectsDuringGame = 1

Allows use of MusicStudioV2.2's sound effects and music extension feature. Plays sound effects from the instruments of the current tune and also in game music.

TitleScreen_AnimatingSprites = 1

Replaces the standard SEUCK Title screen effect with Armalyte style balls over the title screen. Of course the multiplexor animation doesn't always have to be balls :)

Scroller_LinkedEnemyTest = 1

Checks for any linked enemies, and makes those explode as a whole. Be very careful when using this feature. Since enemies which use a linked path and are not connected together will explode as a whole. This feature is good for end of level bosses and big space ships, etc.

Scroller_LinkedPlayers = 1

Links players in a set position. This is handy for games where you would like to bolt two players together to form a huge space ship, a ninja or whatever. Setting the value of Scroller_LinkedPlayersOffsetX, and Scroller_LinkedPlayersOffsetY will set up the position for both players to form an object. If you use SEUCK, make sure players are EXACTLY the same speed, otherwise strange results will occur.



ScrollerSingleScoreLives = 1

Player 1 and player 2 shares the same score, and amount of lives. However, should the game be set to TWIN MODE, after one player has lost its last life, the other player has only one life left. 

Scroller_TwinMode = 1

Allows use of two separate players but shares the same joystick control. This is handy for a one player team style game, where you could have two people in two different dimensions, etc like in Alf Yngve's Double or Nothing (Which won the SEUCK Compo a few years back).



Scroller_SetSpriteBackgroundPriority = (value)

Allows you to set the sprites to be either in front, or go behind parts of the background. For example Wacky Waste allows use of the sprite behind background feature, in order to hide one player when in race mode, or walking mode.

CollisionAllowEscape = 1

SEUCK games always had a problem where the player gets stuck when spawning in invincibility mode over characters that represent the deadly/stop char or higher. This feature can prevent the player from getting stuck when re spawning, before the player's invincibility timer runs out.

Scroller_NoMusic = 1

Disables all music

Paralax_Enable = 1

Enables the block parallax scrolling feature (See background animation feature to find out more about this (Chapter 4).

ExamplePlayerBulletTwoWay = 1

Generates a two way firing feature, any time the player shoots,one bullet fires the default direction, and another can fire a set direction, according to the table set in PlayerControl.a. It is possible to make it a 3 way firing feature, but I won't be telling you how that was done. That's just my secret :)

EnemyAITest = 1

Tests artificial intelligence of a selected enemy. Basically replaces all of one enemy object with a chosen enemy. Enabled the ENEMYTST.P00 in ScrollerDataMacro.a to see what happens.

EnemyAimTest = 1

Tests chosen enemies to aim for the player's current position in the game area - before firing.

OverrideDefaultAnimationDirection = 1

Uses the last directional position of an object. SEUCK usually sets enemy objects to directional up, after they have stopped. This feature overrides this.

WackyWaste = 1

Defining this will turn on the player switching mode, according to the level which the player is already at.



EnemyBulletToPlayerBulletTest = 1

Makes enemy bullets shootable, and morph into a chosen object should the player shoot it.

ScorePlayer1XPos / ScorePlayer2XPos

X-Position for the default SEUCK score panel. If you wanted to make a new score panel (Chapter 8 will show you 2 methods on this). Extra code will be required.


BACK TO TOP

           

8. MAKING A SCORE PANEL

In this chapter we take a look at the basics of making a new score panel for your Redux program. SEUCK has always used the same scoring panel. However SEUCK Redux allows you to implement even better scoring panels, for either vertical, horizontal or multiscrolling programs. In this chapter I give you a quick start on how to use a custom charset panel display (See Hover Raider 2016), and also how to do a single sprite status panel for a 1 player game.

So how is the score panel done?. A normal SEUCK scoring panel, checks for the value of player 1's score, or player 2's score and then creates a subroutine which renders a character set into the lower border. You can see where the status panel sprites are located in SetupIRQs.a (Look up BottomBorder, and you'll see as you scroll down a bit further the vertical position for the score sprites, and slightly further along, the horizontal position of the player sprites. Look for and have a play with the values of this:

; Now update the rest of the sprite pointers to display what we want
    ; Turn off multi colour here so we don't get rubbish at the bottom of the screen sprite data.
    ; If this is done earlier in the raster the timing is slightly wrong
    lda #0
    sta VIC2SpriteMulticolour

    ; Here there is more raster time.
    lda # ( ((ScorePlayer1XPos+0)/256) << 0 ) + ( ((ScorePlayer1XPos+24)/256) << 1 ) + ( ((ScorePlayer1XPos+48)/256) << 2 ) + ( ((ScorePlayer1XPos+72)/256) << 3 ) + ( ((ScorePlayer2XPos+0)/256) << 4 ) + ( ((ScorePlayer2XPos+24)/256) << 5 ) + ( ((ScorePlayer2XPos+48)/256) << 6 ) + ( ((ScorePlayer2XPos+72)/256) << 7 )
    sta VIC2SpriteXMSB
    lda #<(ScorePlayer1XPos+0)
    sta VIC2Sprite0X
    lda #<(ScorePlayer1XPos+24)
    sta VIC2Sprite1X
    lda #<(ScorePlayer1XPos+48)
    sta VIC2Sprite2X
    lda #<(ScorePlayer1XPos+72)
    sta VIC2Sprite3X
    lda #<(ScorePlayer2XPos+0)
    sta VIC2Sprite4X
    lda #<(ScorePlayer2XPos+24)
    sta VIC2Sprite5X
    lda #<(ScorePlayer2XPos+48)
    sta VIC2Sprite6X
    lda #<(ScorePlayer2XPos+72)
    sta VIC2Sprite7X
   
With this part of the code, it is possible to alter the X position of the sprites to build / construct a better scoring / status panel under the border. All you need to do is modify the code to change a sprite score panel. If the lower border isn't used, and a char panel is to be used instead. You don't need to trigger the sprite multiplexor scoring code. It is also possible to change the colour of the status panel in SetupIRQs.a Have a proper scroll through the source code and look up the colour setting for player 1 or player 2. Then play around with values #$00-#$0f and store to the sprite colour panel. You'll get some results.



8A. Making the a Sprite Score Panel


The same old SEUCK status panel has always been there. You want to make something more different and cooler? Well, modifying SetupIRQ.a and adding a little extra code can do exactly that. In this small part of this chapter. We are going to do a sprite based score panel for a chosen SEUCK game. For this task, I have chosen Zap Fight 2 - Zapped into Oblivion. Before we do any code, we want to setup the sprite type to represent various objects. One object (I used a star for this) is a Star, for the Lives icon, and the rest are numbers, to represent the scoring and lives. Draw what you like using SpritePad, or any other sprite editor. Here's what Zap Fight's panel sprites will look like:
 


What if we wanted to make the above become something like this: ????



The first thing you would need to do is to create your own sprites for the status panel in Charpad (or whatever), export it to C64 PRG format (If you export as raw format, just remove the ,,2 command in !bin "filename.ext",,2. Import the sprite data into the source ScrollerData.a where there is room for data growth (or after $f000 in memory). Before *=$8000 (if you have enough room) add a new label and binary import, which is:

SpritePanel
!bin "StatusPanel.prg",,2 (or !bin "StatusPanel.raw")

Also underneath it (or in any other free area of the code) create a subroutine to place them in correct memory every time a new game starts:

InitStatusSprites
                ldx #$00
MoveSpriteData  lda SpritePanel,x
                sta $0900,x
                lda SpritePanel+$100,x
                sta $0a00,x
                lda SpritePanel+$200,x
                sta $0b00,x
                inx
                bne MoveSpriteData
                rts

This will not do anything yet, because you would need to add some code which will copy the status panel to memory the sprite panel should be relocated to $0900-$0bc0 ($0bc0 and higher is used for different data or code). Let's do a score copy subroutine. Where to place it? ScrollMain.a is probably the best place to store it before the music of sfx init routine in ScrollMain.a (or after it) add the following command:

                jsr InitStatusSprites

Now that will init status sprites, however we want to actually render the score and lives counters with the sprite displays. So let's first of all position those, and then setup the scoring / lives system. This can be done in SetupIRQs.a. Look up the label BottomBorder2, and make these current adjustments, to set up the position of the new status panel sprites:

NOTE: ONLY COMPLIES TO 1 PLAYER GAMES ONLY, like Zap Fight, Nuclear Strike Force, etc. This example picks sprites 1 and 2 to use MSB (for the other end of the screen). 

    lda #%00000011;

    sta VIC2SpriteXMSB
    lda #$20
    sta VIC2Sprite0X
    lda #$3a
    sta VIC2Sprite1X
    lda #$20
    sta VIC2Sprite2X
    lda #$20+$1a
    sta VIC2Sprite3X
    lda #$20+2*$1a
    sta VIC2Sprite4X
    lda #$20+3*$1a
    sta VIC2Sprite5X
    lda #$20+4*$1a
    sta VIC2Sprite6X
    lda #$20+5*$1a
    sta VIC2Sprite7X

Now underneath we shall render the main score panel.

    ;RENDER
    lda #$ff
    sta $d01c
    sta $d015 ;Sprites + Multicolour switched on

    ; Sprite score pointers. $fdc0-ffbf

    ldx #$22+12        ;Display star (Lives icon)
    stx $07f8

    ;Check whether or not player 1 reaches higher
    ;than 9 lives. If so, then flip back one life
    ;on the counter.

Player1Lives

    lda Player1Information+PlayerGameOffset_Lives
    cmp #$09 ;If over
    bne LivesSetOK

    ;Reset number of lives to 9 - Value of 0 represents 1 on status panel
    lda #$08
    sta Player1Information+PlayerGameOffset_Lives

LivesSetOK

    lda Player1Information+PlayerGameOffset_Lives

    clc
    adc #$25 ;Sprite value for lives + 1 ($0940)
    sta $07f9
   
    lda ScorePlayer1    ;Read first pointer on score panel
    clc
    adc #$24    ;ScorePlayer1 + the value of the sprite at $0900-$0bc0 = the actual sprite to display
    sta $07fa           ;Store to sprite 2

    lda ScorePlayer1+1  ;Read second pointer on score panel
    clc                   
    adc #$24            ;Same calculation as above
    sta $07fb           ;Store to sprite 3

    lda ScorePlayer1+2  ;Read third pointer on score panel
    clc                   
    adc #$24            ;Guess what... More of the same
    sta $07fc           ;Store to sprite 4

    lda ScorePlayer1+3  ;Read fourth pointer on score panel
    clc
    adc #$24            ;Calculate
    sta $07fd           ;Store to sprite 5

    lda ScorePlayer1+4  ;Read fith pointer on score panel
    clc
    adc #$24            ;Calculate
    sta $07fe           ;Store to sprite 6

    lda ScorePlayer1+5  ;Read sixth pointer on score panel
    clc
    adc #$24            ;Calculate
    sta $07ff           ;Store to sprite 7

    lda #$09            ;Sprite multicolour #1 = Brown
    sta $d025

    lda #$07            ;Sprite multiccolour #2 = Yellow
    sta $d026
   
    lda #$08            ;Score multicolour for all sprites
    sta $d027
    sta $d028
    sta $d029
    sta $d02a
    sta $d02b
    sta $d02c
    sta $d02d
    sta $d02e

All of these will now give you a new score panel for the player. However, if you assemble the code straight away, you will spot a small glitch in the game. The player object's multicolour is the same colour as the status panel. In order to fix this issue, you will need to look up in SetupIRQs.a .retNMI and before .retNMI add the the values of the sprite multicolour colours for your game. Here's what Zap Fight 2 used:

    lda #$00 ;Black
    sta $d025

    lda #$0e ;Light blue
    sta $d026

.retNMI

And there your go. A new score panel made up of 8 sprites.

BACK TO TOP



8B. MAKING A CHAR BASED SCORE PANEL

In this part of Chapter 8, we show you how to actually make a char based score panel. It will then be up to you to work out how to make a proper panel, yourself. Before we actually make a char based score panel, I must warn you that using this method, will allow enemies to shoot upwards (when behind the score panel) and the bullets will appear. So should you wish to use a character based score panel in your SEUCK creations. Make sure enemy bullets sprites are not visible, when firing any of the upward directions - unless you intend to have sneaky firing of course :) Also, if you use the char status panel method - Make sure you update your player's lower position where the player can STOP over the panel. Otherwise the player will just go underneath it. It doesn't really matter for the enemies that go up. The size of your score panel should be like the example below

4 chars down, 40 chars across


Your panel doesn't have to use large characters if you don't wish it to. Just make sure you use the CharPad, to save the file as CTM CharPad project format or export 3 files, Panel Charset, Screen RAM and Colour RAM. Now in ScrollEntry.a Disable the Scroller_FullScreen, and then enable Scroller_UseDemoScorePanel by uncommenting it out. After you have done this, if you do a test run, you'll see a test score panel. All you need to do is go to ScrollerData.a and replace this with the filename of your charset project. Then you're done ... Test run the source, and you will notice your score panel is displayed. But what if you wish to render score, lives, etc into the code?. Well, all you would need to do is create a subroutine in ScrollMain.a, via a loop and call a routine before or after jsr MusicPlayerPlay, which is as follows:

        jsr RenderScore

The Render score code look something like this:

RenderScore
           ldx #$00
scrloop    lda ScorePlayer1,x
           clc
           adc #TFNC ;TFNC = The value of the first number char (Custom digit 0) in your charset
           sta [ScoreCharPos1],x ;ScoreCharPos is the chosen char position for player 1's score. Ranging from $0720-$0798

           lda ScorePlayer2,x ;If you have a 2 player mode, you can do the same
           clc
           adc #TFNC
           sta [ScoreCharPos2],x
;ScoreCharPos is the chosen char position for player 2's score. Ranging from $0720-$0798
           inx
           cpx #$06 ;Do 6 chars

           lda Player1Information+PlayerGameOffset_Lives
           clc
           adc #TFNC
           sta [LivesCharPos1]   ;Lives char is the chosen char position for player 1's lives. Ranging from $0720-$0798
       
           lda Player2Infromation+PlayerGameOffset_Lives
           clc
           adc #TFNC
           sta [LivesCharPos2]
           rts

... and that is how you do a charset based score panel. OH... WAIT - Not quite there yet. There is something I have forgot to mention. You will want to know where you can change the colour of the score panel. Am I right? Yes?, okay. Just add this command before RTS.

          
            lda #[Multicolour1]
            sta $d022
            lda #[Multicolour2]
            sta $d023

9. CREATING A NEW FRONT END

In this final chapter, we take a look at creating a new front end. It is possible to keep the old SEUCK title screen, with the old scrolling raster bars and all that. However one you have seen one basic presentation like that you have seen them all. Every new game made in Redux should really have a brand new front end presentation. A title screen of today / or front end consists of a logo with credits, optional hi score table, game options, etc with music. In this chapter we will be showing you how to turn a basic SEUCK title screen into to something more spectacular.

An old default SEUCK game title screen looks like this:



And after a major transformation - It looks like this:



This title screen didn't use SEUCK Redux, but was made as a prize for the SEUCK Compo 2013. The title screen consists of a logo, with some colour washing effects and swirling sprites, page flip and scroll text. SEUCK Redux doesn't have enough room for bitmap with colour RAM and Video RAM in place. Logos should always be in charset format.

BACK TO TOP



9A. PUTTING LOGO, CHARSET AND TEXT ON TO THE TITLE SCREEN

So then, how do we make an actual new front end in SEUCK Redux? Well, first of all you need to have two sets of charset graphics. The first of which is the main logo charset (and matrix), followed by a text charset. You can place both of those in the ScrollerData.a source, where there is enough memory for data growth, or in the $f000-$ff00 range. When editing the title screen. The first thing you would need to do is either comment out all the code that does the colour washing trick, and also alter / add more raster splits using CMP $D012 : BNE *-3 commands. Before we do this, have your graphics prepared and in ScrollerData.a add the following:

;There is memory for data growth

LogoCharset
            !bin "logofont.prg",,2
LogoMatrix
            !bin "logoscreen.prg",,2
TextCharset
            !bin "myfont.prg",,2
           
            ;Still text to add to your front end
           
!ct scr

CreditsLine1
            !text " game design, graphics and sound effects"
CreditsLine2
            !text "                by your name            "
CreditsLine3
            !text "        additional programming by       "
CreditsLine4
            !text "        martin piper and your name      "
CreditsLine5
            !text "         music composed by whoever      "
CreditsLine6
            !text "             press fire to start        "


            ;Scroll text for the title screen presentation

ScrollMess  !text "name of game ... game design, graphics and sound effects by your name "
            !text "... additional programming by martin piper and your name ... music com"
            !text "posed by composer ... (c)2016 your name / group ... press fire to play"
            !text " and enjoy ...                                                        "
            !byte 0 ;Text restart byte value
xpos        !byte 0 ;Soft scroll control counter

Now let's edit the title screen. First of all, you will want to use the custom charset and logo charset on your title screen. In order to be able to do this, you would need to change the command that relocates the SEUCK charset data and places it on to the screen. Look up the command

;Copy the SEUCK title screen data to relevent places

... and then replace it all with the new code. Also remove the complete command

!ifdef TitleScreen_AnimatingSprites {
    lda TitleScreenBallSprites,x
    sta $0a00,x
    lda TitleScreenBallSprites+$100,x
    sta $0b00,x
}

Replace it with a subroutine, which can copy the logo data to memory, and the new titlescreen charset. Do as follows in TitleScreen.a

    ldx #$00
.l1 lda LogoCharset,x
    sta $0800,x
    lda LogoCharset+$100,x
    sta $0900,x
    lda LogoCharset+$200,x
    sta $0a00,x
    lda LogoCharset+$300,x
    sta $0b00,x
    lda TextCharset,x
    sta $0c00,x
    lda TextCharset+$100,x
    sta $0d00,x
    lda TextCharset+$200,x
    sta $0e00,x
    lda TextCharset+$300,x
    sta $0f00,x
    inx
    bne .l1


Now fill the entire screen with a blank char. Say for example, the space bar character on the title screen's text charset

    ldx #$00
.fillScreen
    lda #$00

    sta $0400,x
    sta $0500,x
    sta $0600,x
    sta $06e8,x
    inx
    bne .fillScreen

What about drawing the logo and displaying the charset? Well, simply copy the data from the data growth memory, and then place it into the title screen code.Say we had a logo of char 8 rows, we code something like this.

        ldx #$00
.setupTitleCharScreen
        lda LogoMatrix,x
        sta $0400,x ;Top screen area
        lda LogoMatrix+1*40,x
        sta $0400+1*40,x
        lda LogoMatrix+2*40,x
        sta $0400+2*40,x
        lda LogoMatrix+3*40,x
        sta $0400+3*40,x
        lda LogoMatrix+4*40,x
        sta $0400+4*40,x
        lda LogoMatrix+5*40,x
        sta $0400+5*40,x
        lda LogoMatrix+6*40,x
        sta $0400+6*40,x
        lda LogoMatrix+7*40,x
        sta $0400+7*40,x
        lda #$0b             ;Say your logo uses a blue scheme where cyan is
        sta $d800,x          ;the multicoloured charset, and dark blue and light blue
        sta $d800+1*40,x     ;represent the logo background multicolours. We fill the
        sta $d800+2*40,x     ;colour RAM to fill the chosen chars CYAN/Multicolour (or dark grey if not multicolour)
        sta $d800+3*40,x
        sta $d800+4*40,x
        sta $d800+5*40,x
        sta $d800+6*40,x
        sta $d800+7*40,x

        ;Credits text position

        lda CreditsLine1,x
        sta $0400+11*40,x        ;Row 11 of the screen RAM
        lda CreditsLine2,x
        sta $0400+12*40,x        ;Row 12 of the screen RAM
        lda CreditsLine3,x
        sta $0400+14*40,x        ;Row 14 of the screen RAM
        lda CreditsLine4,x
        sta $0400+15*40,x        ;Row 15 of the screen RAM
        lda CreditsLine5,x
        sta $0400+17*40,x        ;Row 17 of the screen RAM
        lda CreditsLine6,x
        sta $0400+19*40,x        ;Row 19 of the screen RAM

        lda #1 ;Colour white for all of the previous char lines
        sta $d800+11*40,x        ;Row 11 of the colour RAM
        sta $d800+12*40,x        ;Row 12 of the colour RAM, etc. ...
        sta $d800+14*40,x
        sta $d800+15*40,x
        sta $d800+17*40,x
        sta $d800+19*40,x
        inx
        cpx #40                    ;If full charset not drawn, fill 40 times
        beq FinishedFillingChars
        jmp .setupTitleCharset

BACK TO TOP


9B. RASTER SPLITS / SCREEN CUTS

Raster splits and screen cuts are good for controlling the main backbone of your front end. These can be used to do synchronized events such as colour washing, controlling a scroll text, etc. In this example, the front end sets up two screen cuts. The top area for the static text, and the bottom for a smooth scrolling message. In TitleScreen.a comment or delete these commands. (To be safe I commented out the command that controls the colour rolling. Add before the comment:

     jsr doScrollText

    ; Use the raster table colour type to calculate the index into the colour table
;    lda RasterColourTableType
;    sec
;    sbc #$10
;    asl
;    asl
;    asl
;    clc
;    adc #<RasterColourTable
;    sta tempWork0

;    lda #>RasterColourTable
;    adc #0        ; And carry any remaining from the above add
;    sta tempWork1
;
    ; Update the table scroll counter every four frames
;.sm1    ldy #0
;.sm2    lda #0
;    bne .noUpdate
;    inc .sm1+1
;    lda .sm1+1
;    and #7
;    sta .sm1+1
;    lda #3
;    sta .sm2+1
;.noUpdate
;    dec .sm2+1
;    ; Wait for the top of the character data to start the raster effect
;    ldx #50+(6*8)
;.l5
;    lda RasterColourTableType
;    cmp #$10
;    ; If we are not doing a raster effect then just use the colour
;    bcc .l6
;    lda (tempWork0),y
;.l6
;    cpx VIC2Raster
;    bne .l6
;    sta VIC2ScreenColour
;    inx
;    inx
!ifdef Scroller_LOTD {
;    dey
} else {
;    iny
}
;    tya
;    and #7
;    tay
;    cpx #50+(20*8)
;    bne .l5
}

Right, now let's replace the old raster code underneath the above command with two screen cuts. One for the static screen, and the other for the scroll text.

testBorder = 1

;Top raster position for title screen static text + logo

                  lda #$32
                  cmp $d012
                  bne *-3
!ifdef testBorder {
                  lda #1
                  sta $d020
}
                  lda #8 ;Smooth scroller off ....
                  sta $d016
                   
;Bottom position for where scrolling text should take place

                  lda #$e2
                  cmp $d012
                  bne *-3

!ifdef testBorder {
                  lda #2
                  sta $d020
}
                  lda xpos ;Smooth scroller on
                  sta $d016

Now let's add a scroll text subroutine, doScrollText to the code. Look up any RTS command that is in TitleScreen.a and underneath it, add this small scroll text subroutine:

doScrollText
                  lda xpos
                  sec
                  sbc #2 ;Speed of smooth scroll
                  and #7
                  sta xpos
                  bcs endscroll

                  ;Loop to scroll a row of chars across to the left

                   ldx #$00
.moveChr           lda $0400+23*40+1,x ;Chosen row to scroll chars back
                   sta $0400+23*40+0,x ;Chosen row 
                   lda #7              ;Select colour for row
                   sta $d800+23*40,x
                   inx
                   cpx #40
                   bne .moveChr

                    ;Now for the crucial part. Detecting an end byte in self-mod

MessRead           lda ScrollMess
                   cmp #$00            ;Check for text restart marker
                   bne StoreToLastChar

                   ;Restart text via Selfmod
                   lda #<ScrollMess ;Low byte of very first text message char
                   sta MessRead+1
                   lda #>ScrollMess ;Hi byte of very first text message char
                   sta MessRead+2
                   jmp MessRead

                   ;Store to the next character the the message to last the char
StoreToLastChar    sta $0400+23*40+39
                  
                   ;Increment lowbyte position
                   inc MessRead+1
                   
                   bne endscroll
                   
                   ;Increment hibyte position
                   inc MessRead+2
                   ;Finished scrolling        
endscroll
                    rts

Finally when you run the front end, you'll notice the scroll text will NOT restart every time a game is over. To be able to restart the scroll text. In the next line after clearing your screen, add the command. Then you're done.

                    lda #<ScrollMess
                    sta MessRead+1
                    lda #>ScrollMess
                    sta MessRead+2

BACK TO TOP

   

9C. FINISHING THINGS OFF - DO IT YOUR WAY

To finalise this chapter, it is possible to add various tricks and features into your front end. You can add counters to make in game options, or a GET READY, GAME OVER, and GAME COMPLETE screen. It is also possible to create the front end the way you like, as long as you can code it yourself. You can also display game sprites by copying those from memory and pasting them to spare memory between $0800-$0fff, should there be no charset overlapping the memory. At the end of the day, using SEUCK Redux it is up to you to design and create your finished game production, and presentation. I wish you all the best of luck with SEUCK Redux, and making your games feel much LESS like SEUCK in the future. :)



BACK TO TOP

IMPORTANT NOTE:

This document was written legally as a short brief reference to the Scroller project source code by Martin Piper. Screen shots may have been taken from some sources, but shouldn't infringe any form of copyright. Any infringement in this document will be respectably removed from this web site, should we hear about it. The goal of SEUCK Redux is to help people who write SEUCK games, enhance their games even further through a new source code, in order to support this tool even more. 
   
Disclaimer:

Some example snapshots of the utility were examples of my own / Martin's productions from the Shoot Em Up Construction Kit by Sensible Software. The Shoot Em Up Construction Kit was a commercial games creating utility that was written back in 1987 and published by Palace Software, then on Budget 1991 Gremlin Graphics. Sideways version of SEUCK is (C)2008 Sensible Software and Jon Wells.

The new game source code in SEUCK Redux is (C)2016+ By Martin Piper and released under GITHUB. Martin has his own blessing for SEUCK Redux to be used for non-commercial or commercial game productions. However, please credit him for part of the code, since most of the source is his :)

If there are any topics I have missed out on this page, which you need to know about. Please contact me at my usual email address. This page will be edited to give more future features should any more come along.