Tutorial 8: Source Code

Hi and Welcome Back.

Thank you for your messages of support, and I’m very aware you just want me to pull my finger out “Just Get On with It!” and get cracking on the tutorials (in the style of Monty Pythons Life of Brian), I also realise that I am slowing down somewhat, and this is purely due to work pressures that pay the bills and mortgage, and trust me I’d rather be doing fun stuff like this!  

In Parallel the MM game itself has evolved and very near readiness for a BETA test for a few select individuals.

If you are following the AGK Forum you will know I experienced a small issuette with Pixel Perfect Collision detection.  After much Caffeine and Head Scratching you will be please to know that I have solved the pixel perfect collision detection in AGK BASIC!  Well…. When I say solved, it is solved in the context of Manic Miner, based on sprite sizes and the games limiting factor (no rotation of sprites).   So I hope you can forgive me for these delays, I’m only human 🙂

And hands up, The London Marathon got in the way this weekend as I popped over to London to watch the runners cross the finish line…  Bit naive I know, turns out the Mall was set up so that the public couldn’t see the runners on the final stretch of the line.  But still the experience of just being there was simply amazing!

Ok, enough excuses, as I am writing Tutorial 8 this evening, I realised it’s going to take a little longer to give a thorough explanation of what is going on (at least to do it any justice) because from here on in it’s going to get slightly tougher and a lot more code.  This tutorial is quite key to the following ones which involve building the levels, animating actors and adding our hero etc etc.

So rather than you wait for me to complete the write up, I’ve taken the unprecedented step of releasing the AGK Source for Tutorial 8 whilst I continue writing this up, so please have a look at the code, play with it, as I’m sure you will have questions that need answering.   (BTW, just press ENTER when the Manic Miner Flashing Logo Appears to get to the main Title Page).

The code starts on the concepts of Game States, and adds functions to play the piano notes whilst you listen to the Blue Danube and scroll the message text on the screen.

You can use this code in your own projects and I would be keen to see what you can do with it.  The best part is the Piano playing code is extensible and so you can easily add up to 10 fingers and customise the notes files found in the media/config folder.

https://www.dropbox.com/s/bbi5hqfdpp28tqp/ManicMinerAGKTutorial8.zip?dl=0

In the mean time, please feel free to experiment with the code, however remember the graphics and music are copyright Andy Noble and may not be reused without his permission.

Thanks for your understanding and patience in advance.  (if you remember the Adverts from the 70’s and early 80s, like British Rail – “We’ll Get There!”).

 

progress 1

Advertisements

Tutorial 7: The Main Title Page

In this tutorial, we’re going to cover the Main Title Page of the game.

Following on from Tutorial 6 where we created the sprite atlas with Andy Nobles artwork, We need to construct the title page, and this is fairly straight forward as we’ll basically load the sprites from the texture atlas and drop them on the screen, towards the end of the tutorial I’ll show you a simple trick to optimise the title screen for performance and squeeze a few more cycles out of AGK BASIC. 

PianoLoadingPage

 Download the Code for this tutorial Here

There are a number of ways you can construct the title page, the obvious one is to create a Single Static Sprite (512 x 384), and if you didn’t need to reuse any portion of that screen again within the game then that is an acceptable method.  The joy of programming means there’s usually many ways to achieve the same result, some are better than others depending on the type of program you are creating.  

However, we want to re-use some of the sub sprites (i.e. the Piano, the Title Bar and of course Miner Willy’s home on the 20th level).

As our previous tutorial already created the sprites as individual images, so we can simply load these and place them on the screen.

We’re also going to add a few new files to our project :-

  • MainTitlePage.agc – Draw the Main Piano Title Page.
  • MainTitlePageV2.agc – Draw the Main Piano Title Page (optimised version)
  • ManicDance.agc – Perform the Willy Dance when the music stops playing.
  • TextHelperFunctions.agc – Miscellaneous functions related to Text/Strings.

MainTitlePage.agc

This will draw the main title page we see in the picture above, and in version one we will simply load the sprites from the texture map and add them to the screen.

MainTitlePageGlobals

But first, some globals and constants 🙂

The constants define the positions that the filler blocks (green hills and cliffs) use to complete Miner Willy’s home.  (The original artwork and Spectrum game had blank spaces where Willy’s Exit is and the platforms resides).

The global variables are :-

  • g_iScrollingMessage – Text ID of the Scrolling Message
  • g_iManicSpriteSheetID – Image ID of the Texture Atlas
  • g_iPlayAreaOffsetX – The X Offset to centre the scene on screen
  • g_iPlayAreaOffsetY – The Y Offset to centre the scene on screen
  • g_iSignalScrollingMessageComplete – Signal the end of the scrolling message.  (We’ll use this to start Demo mode later in the tutorial series).

initialiseMainTitlePage

 

InitialiseMainTitlePage()

This function will perform the following :-

  • Delete All Sprites, Images, Text and Objects held in AGK memory (start from fresh).
  • Set the Clear Colour to Light Grey
  • Set the Border Colour to Black (if you are playing on a device and the screen is adjusted for a virtual screen).
  • Calculate the X and Y offset to centre the GAMEBOARD of (512 x 384 Pixels) within a 640 x 480 Virtual Screen – This allows a border similar to a ZX Spectrum to be displayed.
  • Load the Main Sprite Texture we defined in Tutorial 6.
  • Position the sprites on the screen to create the Piano Title Page.
  • Add the message to the MessageBAR, in this case “Made with AGK2”
  • Set up the scrolling text message.
  • before finally adding the Star of the Show “Willy” to the screen.
If you have a sprite placement editor or tool, that would be a very useful program to have to speed up game development and/or workflow, for now, I’m doing this programmatically to keep things simple.
 

moveScrollingMessage()

Does exactly that!  It simply adjusts the X-Position of the Scrolling Text Sprite two pixels to the left until the text is no longer visible on the screen.
When the text has fully scrolled, it additionally sets a signal to say the message has completed a cycle, reset the message back to the far right and start again.
In the real game, once the message scrolling has completed and the user has not pressed play, the game will demo each level for 5 seconds.  (For now we’ll just restart the scroll).
 
 
moveScrollingMessage
 
 

resetTitlePage()

We’ve added this function to reset the global variables and to correctly deallocate (Tear down) the Main Title Page, this will become obvious once we start adding game states.
 
resetTitlePage
 

ManicDance.AGC

This file contains the functions to make Miner Willy dance on the screen when the music has finished playing.  We use a simple technique using SpriteFrames to create this illusion.
 
Of course, more Globals and Constants!
 
initWillyDance
  • g_iManicDance – Sprite containing the Willy Dance Frames.
  • g_iWillyDanceCounter – A timer counter to adjust the speed Willy Dances.
  • g_iCurrentWillyDance – (Not used)
  • g_iDanceMoves as integer[8] = [1,3,6,7,2,1,7,3] – The Dance Frame Sequence Numbers
  • g_iDanceMoveP – Position in the array above.
     
  • WILLYDANCEWAITTIME 10     – Wait 10 Frames
  • WILLYMAXDANCEFRAMES 7    – reset the Pointer to 0 when this limit is reached.

 

initWillyDance()

This function will load the Willy Dance Sprite if it is not already available.  It does assume that the main Sprite Sheet has been loaded first though.

showWillyDanceOriginalPosition()

This function will load the Willy Dance sprite if it has not been loaded already, initialise the sprite frames and set the dance counters appropriately.

showWillyDanceOriginalPosition

 

danceWillyDance()

This function will make Miner Willy dance by adjusting the Animation Frame according to the array g_iDanceMoves defined earlier.

  • First it will decrement the Tick Counter (currently set to 10 Ticks (10/60ths or 1/6th second) before Willy changes dance position.
  • The Position in the array will be incremented, and then checked to ensure it remains in the arrays bounds (g_iDanceMoves).
  • Before finally getting the desired Frame to display and setting the frame appropriately.

resetTitleMove()

This function simply resets the global variables to their initial startup values.

deallocWillyDance()

This function ensures that the Willy Dance sprite is correctly deallocated (removed from memory)
 

danceWillyDance

TextHelperFunctions.agc

This include file adds some text helper functions that will be used within the game, and it will grow during the course of the tutorial.

TextHelperFunctionsV1

initFixedWidthFont()

We will use this later to include a retro 8 bit font for the game.

messageBar()

This function will take a string as a parameter and correctly centre on screen within the Message Bar graphic the text to display.  In the game we’ll call this to display the level name.

scrollingMessage()

This function takes a string as a parameter and creates the scrolling message we will use on the TitlePage and set the position accordingly.  We also use a Text Scissor defined as the width of the game play area and the height of the text message itself.  Scissors are very useful features of AGK and I think of them as inner windows to sprites, and we’ll use this a lot with the collapsing floor during the level design.

If you attempt to display a sprite outside the scissor window, it will be cut, i.e. not displayed.

Scissor Text

 

main.agc

Finally in main.agc we need to include the new files we’ve created :-

We also set two defaults on this project

SetDefaultMagFilter(0)
SetDefaultMinFilter(0)

The default Min and MagFilter sets the way that sprites are expanded/scaled on screen.  As we are going for a retro 8 bit look, we don’t want anti-aliasing switched on and therefore want the sprites to look blocky.  Setting this to Zero will achieve that effect.

Using the sample code of the project, look at what happens when these two are commented out.  Where you see the green filler blocks positioned on the screen you will see a thin black line appear showing where the images are stitched together and clearly that is undesirable.

Tutorial 7 Main.agc

Initialise Piano Page

Scroll7

All that is left to do is run the code, and you will be presented with the familiar Piano Title Page!

Optimisation

Yes the code works, and so far it’s looking good (and that’s mainly due to Andy Nobles Artwork!) however if we dig a little deeper, we see at a basic performance level what is happening when AGK is rendering the screen frame by frame.

in main.agc I’ve added a debugInfo() function, and this performs the following :-

  • Shows
    • Number of Sprites Drawn Count
    • Number of Sprite Draws Called
    • Pixels Drawn
    • FPS
  • If there are unassigned images (images loaded but not assigned to an operational sprite)
    • The number of unassigned images
    • Some basic info about those unassigned images

Debug7

Simply add this to your DO/SYNC() Loop to display the output.

Here we can see a bit more that’s going on under the AGK Basic covers.  There are eight sprites drawn each frame and approximately 400K pixels drawn each frame.  AGK performance is pretty good for an interpreted language, but surely we can squeeze some more performance out of AGK?

Draw Counts

Currently and simply, all sprites loaded are being drawn in turn one by one every frame, and I’ve tried to represent it in the picture below as AGK layers each sprite individually.

MMZorder

However, the majority of the sprites remain static (Miner Willy’s Home, The Air Bar, The Piano etc) and the only sprites to move are Miner Willy himself and the scrolling text message.  (until we add the piano sequence).

So how can we improve performance?

The answer is to use a simple technique to create the static sprites onto a backbuffer, copy the image created to create one sprite, and then delete the individual sprites themselves.  (In a nutshell go back to the start and create one main sprite).

I have created in the project folder 

MainTitlePageV2.agc

This contains the changes made to optimise performance of the Title Page.  In main.agc simply change the #include “MainTitlePage.agc” to #include “MainTitlePageV2.agc” and re-run the program to see the difference it makes!

Optimisied Title Page

So what’s changed?

We still load the individual sprites from the Texture Atlas earlier, however this time we’ve added the following :-

Optimisation

Swap() switches the backbuffer to the screen and clears the backbuffer ready for rendering the next frame.

We then explicitly clear the screen before calling Render() which basically draws all sprites and text to the screen.  Before finally creating a new sprite 

  • g_iMainTitlePage = CreateSprite( GetImage(0,0,GAMEAREAWIDTH,GAMEAREAHEIGHT) )
  • setspriteSize( g_iMainTitlePage, GAMEAREAWIDTH, GAMEAREAHEIGHT )
  • ClearScreen()

The sprite is created with the game board size (512 x 384 Pixels), and to ensure that the sprites are scaled correctly we also explicitly set the sprite size by calling SetSpriteSize()  (Thanks to Paul Johnson for making me aware of this, as my original game didn’t scale properly when going full screen!)

Once this new sprite has been created, which is basically a snapshot of the screen, we delete the individual sprites loaded to free up memory, and we do this by calling the following :-

Cleanup on Aisle 2

So was this extra effort worth it?

Well if we run the program again with the debugInfo being displayed we see something like :-

Optimised Result

This has resulted in reducing the sprites drawn from 8 to 2 (only 25% draws now required), it has interestingly increased the Sprite Draw Calls to 3 – I’m not sure why.  But more importantly the number of pixels drawn has reduced from 413480 to 253992 almost (40% decrease).

On a PC/Mac or Linux Machine you probably wouldn’t notice the difference this makes, but if you are targeting a lower end Android or iOS device those extra cycles can make a huge difference to frame rate and performance, especially with complex projects where you are trying to maximise the number of sprites/animations on screen.

We will continue to use this simple technique throughout the project.

Your Feedback Needed!

Going forward the project will become more complex, and I’m looking for your feedback to help shape the level of detail you want to see in these tutorials.  Less info/More Info, too dry, how can I improve the quality of information to you?

Coming up next :-

Animating the Piano to play the musical notes to “The Blue Danube” or any tune you wish to code up.

Don’t forget to check us out on FaceBook https://www.facebook.com/WonkyPix

The more Shares and Likes you can help us achieve, the closer you’ll be to receiving the full source code of the project to customise your own way!

Also checkout our main website http://www.wonkypix.com, even help support us buy downloading our games from the AppStore

Thanks for tuning in!

Collision Detection Test 1

I’ve been so busy with my real job, I’ve not had as much time as I would have liked to complete this remake.  However, here’s a short video showing the simple game mechanics of Miner Willy and how he jumps around the screen.  Very simple collision detection has been included here, I will now work on the collapsible platforms and conveyors next.

The grid demonstrates how collision detection works as Grid level, and this is important before we finally include Pixel Perfect Collision detection as found in games like “Technician Ted”.

Don’t forget to check us out on FaceBook https://www.facebook.com/WonkyPix

The more Shares and Likes you can help us achieve, the closer you’ll be to receiving the full source code of the project to customise your own way!

Also checkout our main website http://www.wonkypix.com

Thanks for tuning in!

Adding Tape Loading Sounds to the Simulation

Welcome back to the final part of creating the Authentic Tape Loading Sequence, in this tutorial, we’ll add the sounds that are associated with the flashing header and data when a ZX Spectrum or other Tape Based systems loads, and the final effect will be similar to the video.

Create and add a new file to the project called SoundManager.agc

Download the Source Code

The code is simply a place holder for now, and we will be enhance it during the project.  The more astute of you will know that you can probably achieve the same effect in a lot fewer lines of code!

SoundManagerSoundManager.agc

As you have come to expect, there are new constants defined, and a TYPE defined called soundInfo, this new type will hold the data structure for sound we will load in the game.

type soundInfo
 soundID as integer // AGK Sound ID when created
soundName as string // Filename of the Sound
soundLoop as integer // Should this sound loop?
soundVolume as integer // initial volume of this sound.
endtype

This data structure will be used at a later date as a helper to manage more sounds.

For now, we’ve cheated and defined two global variables to hold the DATA Sound and the HEADER Sound.

The function loadAllSounds() will load all sounds defined in the project, for now as we only have two, we’ll keep it simple.

The function loadSoundFromFile(), will attempt to load the sound filename supplied.  If it is unable to locate the sound file, an error message will be displayed on screen, otherwise the sound is loaded into memory, a sound TYPE is defined and populated with information provided to the variables passed in the call to the function, (Filename, Loop Flag and Volume) including the newly created SoundID returned from LoadSound().  

The soundInfo will be added to a LINKED LIST before finally exiting with the SoundID you can use to play the sound.  (we will cover LINKED LISTS in AGK later in the project as they are used extensively for managing actors and sprites).

The function stopAllSounds() and removeAllSounds() will do just that, stop all sounds playing, and is a placeholder for now.

Finally, we add some temporary code to the loadCassette() function we defined in the previous tutorial to play the correct sound whilst the virtual cassette is loading.

Load Cassette V2

We simply check the condition that the Virtual Cassette counter has reached zero and ready for the next TAPE state change, then to be on the safe side, stop all sounds from playing.  Before selecting which sound we want to play, set the volume to 100 (Maximum Volume) and the loop flag to 1 (Repeat forever).  This allows you to change the timings of your tape loading simulation without having to resample the Cassette loading sounds.

In main.agc we add the following lines of code to load the sounds before we start the main game loop.

 

New Main Tutorial 5

MainSound 2

Main.agc 

Compile and run!

And that concludes how to create the ZX Spectrum Tape Loading Screen!  Finally I hear you cry.

Coming up….

Creating the PIANO Screen and some optimisation tricks to reduce GPU Calls and Draws to help speed code and optimise for less capable devices.

Don’t forget to check us out on FaceBook https://www.facebook.com/WonkyPix

The more Shares and Likes you can help us achieve, the closer you’ll be to receiving the full source code of the project to customise your own way!

Also checkout our main website http://www.wonkypix.com

Thanks for tuning in!

Creating a ZX Spectrum Cassette Loading – Part 2

Welcome back to the forth tutorial in the Manic Miner Remake series using AGK BASIC.  In today’s post we’ll show you how to enhance the Tape Loader Function from the previous tutorial to automate the tape loading process which you can use to enhance your games.

The video shows the effect in action.


The effect we will achieve

Download the Source Code

To do this, we’ve added a set of Helper Functions in a new file called TapeController.agc which will initialise a Virtual Cassette and run through a sequence as though a real cassette is loading.  You can easily adapt the code for your own projects and add new features.

We will also introduce a concept of States which keep track of what the cassette is currently doing, and update the states based on the events you define.  So let’s dive in!

Tape Controller GlobalsGlobals and Constants Used.
 

As usual we’ll add some constants for the TAPE STATES , (this is where you add your own states when required), just ensure they are numerically unique.  i.e. you cannot have two TAPESTATES defined to the same value if you want them to work.

The states we use in this tutorial are :-

TAPENOACTION – No Action to Perform
TAPESHOWLOADING – Show the Loading Message on the Screen
TAPESHOWANIMATEDSCREEN – Show the Manic Miner Logo

Other states are defined for future use!

We also define a new TYPE called cassetteSection, this type is used to keep track of the different sections of the Virtual Cassette Tape,
for example waiting for the Cassette, The Header and Data, in addition to any special functions we want to call.

The global variables will keep track of the different cassette states, counters and array of cassette functions we’ll cover off further down the tutorial.

rewind The Cassette TaperewindCassetteTape() Function

The rewindCassetteTape function will simulate resetting the cassette tape back to the start, so you can start the reloading process again (if you have programmatically reset your program to the very beginning or just want to see the effect again.

Load Cassette FunctionloadCassette() Function

 This function is where the automation magic happens, and is the primary function you will call inside your game loop (during the tape loading stage).

Lines 67 to 77: Check to see if the Tape is Fully rewound (Is g_TapeFullyRewound = 0 ?)  If not then we will initialise the cassette from the beginning, in addition to initialising the Manic Miner colour Blocks.

Line 80: Calls the updateLines() function to update the raster lines on the screen.

Line 84: Checks to see if we have reached the end of the virtual cassette, and if so exits the function immediately and returns a 1

Line 88: Checks to see if the g_TapeControllerCounter = 0, if so it must be time to get the next cassette function.

Lines 89 to 100: Gets the next cassette state (WAIT, HEADER or DATA), Sets the Counter (Duration), and processes the Cassette Function we require.  It also invalidates the g_timerCounter for the raster header to ensure that it is updated on the next cycle, before finally incrementing the Virtual Cassette Counter.

Lines 104: Decrements the Cassette Controller Counter (The duration as it heads towards 0)

Lines 110 – 113: Finally update the Flashing Manic Miner Blocks if they have been created and on the screen.  I should probably move that function into a state, but it will suffice for now.

Line 115: Exits the function with 0 which means there is more of the cassette to process.

The duration is measured in Ticks, which at 60 FPS each Tick is calculated as 1/60th of a second.  If your device can not achieve 60FPS, or you limit the FPS, you may need to adjust the timings to suit.  A much better way of doing this is using timers if you need exact timing of these functions.

 

processCassetteFunctionprocessCassetteFunction()


This helper function, is where you will add new TAPESTATES for your programs, and in this example fairly crude.

TAPENOACTION: Do Nothing, basically a NOP (No Operation)

TAPESHOWLOADING: Call a helper function to display the message “Program: ManicMiner”

TAPESHOWANIMATEDSCREEN: Call the helper function to draw the MM Game Blocks on the screen

initialiseCassetteDataTypesinitialiseCassetteDataTypes()

This helper function defines the cassette states in our virtual cassette.  Using a global array g_cassetteTitleOrder we add the functions/features that make up our cassette tape, which are :-

Step 1:
Wait 45 Ticks
Display the Tape Header for 60 Ticks
Show Data for 10 ticks.

Step 2:
Wait 60 Ticks and Display the Loading Message on the screen to simulate we’ve loaded a small program.  
Show the Header for 60 Ticks
Show the Data Bars for 50 Ticks and display the MM loading Logo whilst the data bars are moving to simulate the blocks loading with the data.

Step 3:
Wait 45 Ticks
Show the Header for 45 Ticks
Display Data Bars for 12000 Ticks to simulate the game program is loading.

Finally we have a helper function to display text on the screen

programLoadingprogramLoading()

This helper function simply uses the system default font to display a message in black at a specific screen position.

To see this work, we have amended the Main.agc to look like the following :-

Tutorial4Main

We have only two functions to call.  

InitialiseTapeLoader() – To initialise the Cassette
loadCassette() – To run through the Virtual Cassette Tape Order.

The additional functionality is there so you can press SPACE to reset the cassette and see the effect again from the beginning.

Next up, adding authentic sounds to the Tape Loading process, using the Audacity tool before finally getting to the Piano Screen.

Don’t forget to check us out on FaceBook https://www.facebook.com/WonkyPix

The more Shares and Likes you can help us achieve, the closer you’ll be to receiving the full source code of the project to customise your own way!

Also checkout our main website http://www.wonkypix.com

Thanks for tuning in! 

initialiseCassetteDataTypes()

Creating a ZX Spectrum Cassette Loading Screen Simulation

Welcome back to the third tutorial in the Manic Miner Remake series using AGK.  In today’s post we’ll cover the ZX Spectrum Cassette Loading Simulator using AGK2 BASIC, an example of the effect will look like the video below, you can customise these functions for your own purpose, and if you do use the effect, drop me a comment below I’d love to see how you’ve put these routines to best use in your projects!


The effect we will achieve

Download the Source Code 

How did we simulate the loading bars on the screen?  The simple answer is that AGK is rendering 241 sprites in realtime for our selected screen size.  The screen height is 480 pixels, and we create each raster line  two pixels in height.  If your project utlises a larger screen size, then more lines will be generated, the code will adjust for the screen size (provided you change the SCREENHEIGHT and SCREENWIDTH Constants).

We create 240 sprites (lines) in height using a single 2 x 2 pixel solid white sprite that is stretched to the width of the screen, add one large sprite to show the game play/screen area where graphics and text will be displayed in the game area.  Very simply it looks something like the picture below (a cutdown version for illustration purposes).

Raster LinesRaster Lines and Game Display Sprite

In fact all the raster lines and game area are created by one art image asset!   By keeping track of all 240 sprites, the colours of each line can be changed using the SetSpriteColor function of AGK.
 

Cassette ConstantsConstants

As always, I like to keep my programs as parameterised as much as possible (this makes maintenance easier, and more reliable than my memory 🙂 ), most of these are self explanatory, however as we will be moving into BIT Theory, it’s worth pointing out the constants for LSB (Least Significant Bit) and MSB (Most Significant Bit).

AGK Integers are represented as 4 bytes or 32 bits of data.  When the Least Significant Bit is set to One, the binary value is 00000000 00000000 00000000 00000001, and when the Most Significant Bit is set to One, the Binary Value is 10000000 00000000 00000000 00000000.  If all bits need to be set then in Binary it will become 11111111 11111111 11111111 11111111 which is represented as 0xFFFFFFFF in hexadecimal (Base 16).

To make the effect work, Z-Depths are defined the Z-Depth of the sprites, and so the RasterLines have a higher value assigned than the GAMEPLAYAREA, the means that the raster lines will be rendered first and therefore behind the gameplay area.

There are three cassette loading states, TAPESTATEWAIT, TAPESTATEHEADER and TAPESTSTATEDATA,

TAPEWAITSTATE will simply flash all the raster lines in unison to be either Red or Cyan in colour as though the ZX Spectrum is waiting for the cassette to find some data.  The effect is that the screen appears to be flashing one solid colour.

TAPESTATEHEADER will create the header block effect with alternating blocks of Red and Cyan on the screen and give the appearance that the blocks are moving up the screen.  (You can switch these to lines to scroll down by modifying the updateLines() function and change the direction to HEADERDIRECTDOWN

TAPESTATEDATA will flash variable heights of lines in Blue and Yellow to simulate that the virtual Cassette is loading data.

Play the video at the top of this entry to see the effects in action.

CassetteGlobalsCassette Globals

If you aren’t familiar with types in AGK, these are used to create your own custom variables!  How cool is that? It is simply a way of creating a data structure (a block of custom data that can be referenced by variable names), and we create an array of these types on line 61.

The first function in your program needs to call resetTapeLoader() this will reset global variables to their initial startup values, to ensure you can continue to reuse the Cassette simulator if you restart your program within code/logic.

CassetteResetReset Tape Loader Global Variables

The second function to call is InitialiseTapeLoader() This is where the raster lines are created and placed on screen, working its way through the screen height, it will load an image (2 x 2 White Pixel), stretch the pixel to the screen width, and then set the X position to 0, and Y position to 2 times the line count until the screen is filled.

Then finally, loading another white pixel and stretching this to the GAMEPLAYAREAWIDTH and GAMEPLAYAREAHEIGHT defined in our constants, and centring this on the screen.  The original ZX Spectrum initial screen was Grey and so we set the colours appropriately RGB Value of (207, 207, 207)

CassetteInitCreating the initial screen.

A helper function setRasterLinesWithColour() will set a single raster line with one of four predefined colours, whilst the updateLines() will be called for each Sync() loop to update the raster effect depending on the current g_tapeState

You should only need to call updateLines() in your code to update the cassette simulation.  The global variable g_tapeState is set to the cassette simulation we want to display.

Cassette Raster ControlsUpdateLines and Colour Helper Function

flashScreenPeriodic() is straight forward.  This will simply colour all of the raster lines on display with one of two colours, Red or Cyan.

FlashScreenPeriodicFlash Screen Periodic

flashScreenDataReceived() function will randomly set the raster bars to two colours (Blue or Yellow), to make the effect realistic we have a minimum value and maximum value that the data bars can be (again parameter driven by using the DATAFLASHRATEMINIMUM and DATAFLASHRATE parameters.  You can experiment with these #CONSTANTS  to tweak the effect in your own project.

flashScreenDataReceivedflashScreenDataReceived


Finally, the most complicated part of the simulation is how the header bars are rendered and given the appearance they are scrolling upwards.

First we calculate the number of bits required to create the effect and then round up to multiples of Red and Cyan Bars we want on the screen, I’ve set the value to be 24 bars (12 Red, 12 Cyan) on the screen with a height of 10 pixels, 240 Lines requires 240 Bits to represent if a raster line is turned ON or OFF.  However 240 / 32 = 7.5 Bytes, therefore we have to round up and allow for some margin of error, and therefore the Ceil() function helps round up our calculation to work out the right number of bytes.

Next we check if the header raster is valid, and if this is the first time the function has been executed since displaying DATA or WAIT we create the raster bars by setting the Raster set of Bits ON or OFF.

Finally, depending on the direction of the header (up or down) we simply shift the bits along the bit map (left for up, right for down), the diagram below illustrates what we are doing (Hopefully?!?), try to think of this as a really big integer which is at least 240 bits in length.  If moving the bars up the screen we take the left most bit (the Carry Flag) before it drops off, move all the bits to the left, and finally pop the carry bit at back at the right most position.  The whole BIT pattern appears to be rotating along smoothly.  We then reset all the colours on the raster lines, and the visual effect is that the data bars are moving upwards!

BitShifting

 

flashRasterHeader

flashRasterHeader2

 

Finally, we have some helper functions to render the rasterLines on screen i.e. set each line to the correct colour, in addition to make it easier to set or get a bit from the Bitmask, two functions getRasterBitFromIndex and serRasterBitFromIndex and resetRasterArray.

renderRaster

 

To demonstrate the code, we’ve added the following to your main.agc file, when you compile and run the program, press the SPACE Key to switch between the three different Tape Loading modes to see the effects.

Tut3Mainmain.agc changes

To help demonstrate the effect, we added code to show how the you only need three lines of code in your own projects. 

// Pre-initialise

InitialiseTapeLoader()

g_tapeState = TAPESTATEWAIT

// Inside your Game Loop

updateLines()

And if you want to change the effect, set g_tapeState to one of the three #CONSTANTS TAPESTATEWAIT, TAPESTATEHEADER, TAPESTATEDATA

And it’s as simple as that! 🙂

In the next part of the tutorial, we’ll show you a nifty helper function that puts all the tape loading sequence together and triggers the Manic Miner Loading Screen!

Don’t forget to check us out on FaceBook https://www.facebook.com/WonkyPix

The more Likes we get the closer you’ll be to receiving the full source code of the project to customise your own way!

Also checkout our main website http://www.wonkypix.com

Thanks for tuning in!

%d bloggers like this: