I've been testing my editor with the sprite placement code and it works very well with the data being uploaded from CSpect. CSpect only supports 7-bit ESP emulation so a bit of work is needed to support values over 127.
In my NextBASIC editor I can now show how many sprites have been placed for the current screen and can also animate them along their movement paths. I can also edit existing sprites, changing any of their properties, and immediatley view the results. I've also added a 'delete sprite' function. All that I need to do now is test the editor more and then test the sprite data output files in my assembly code.
I'm making good progress with my sprite placement add-on for my screen editor. I can place a sprite and then easily select all of its properties. I just need to define how many sprites have been placed for the current screen and then show each sprite's properties.
I'm enhancing my screen editor, written in NextBASIC, today to include a sprite placement section. Will make mapping out screens and setting up enemy movement patterns and limits much easier. It automatically uploads to my server for including in the source file too for ease.
I've been stress testing the engine and have managed to get 20 enemies with individual movement limits, animation speed, etc all moving with collision detection with the player with no issues.
I've made good progess with my screen editor. I now have a tile select screen and the ability to view just the attributes on their own so you can easily see what you have selected as a solid wall, platform etc. It could do with a few QoL updates, but it's perfectly usable. Next up will be for me to stress test the engine with a large number of enemies on screen, etc.
I've gone back to my screen editor in NextBASIC with the plan of giving it extra functionality when I receive the game graphics. At the moment you can only place one tile pattern, but this needs to be that you can select any tile to be placed. To facilitate this I have written a BASIC program which converts a sprite file for 8x8 tiles. This enables me to draw tiles in the built-in sprite editor normally, instead of in a linear fashion, meaning it is easier to see what they will look like. My converter program then converts the 8x8 tiles to the linear pattern required to place them with the BASIC command, TILE. I am also using the method of reading the tile sheet in a linear fashion in assembly, the same as the TILE command, so this will aid in that too.
I've finished tidying the code up and NextDAW music and AYFX sound effects are fully working now. I've created my own macro too so that instead of writing the assembly each time I want to play a sound effect I just write 'sound x' which is much easier. I'll do this with NextDAW tracks too so I can just write 'music x' and it will setup the relevant track to be played. I may also write macros for 'music stop' and 'music play' to make things a little easier later on.
I have now fully incorporated the AYFX player and NextDAW player, with both working together on interrupts. I have added the ability to select which AY to use for the AYFX player with the plan of having 6-channel NextDAW tracks that use the first 2 AY chips, leaving the 3rd for sound effects. I have tested this with a 6-channel NextDAW track using the first 2 AYs and sound effects being played on the 3rd AY and this works very well. Now, a little bit of work is needed to tidy the code up a bit before I move on to the next task.
Today I've been incorporating Shiru's AYFX player into the code. It works, but I just need to double check the code and then add the ability to select which AY chip the effects play on so they don't interfere with NextDAW.
Memory reorganisation completed. I now have a NextDAW track playing in the game!
I have now incorporated interrupt code and have the code in place for the music player in the main code. Some memory reorganisation is needed before it can be fully implemented as, at present, the NextDAW player requires 4 MMU slots.
I've been able to play a NextDAW track using the NextDAW runtime player today. I've also been exploring interrupts and will look at incorporating the player and interrupts into the main code.
Today I've written a routine for the player colliding with an enemy. I have a basic death routine which just turns the border red and restarts the game. I'll carry out further tests to check performance as currently I'm checking it with 4 enemies on screen. The routine does only 2 checks, one for X and one for Y. After some calculations the carry flag is checked and if it's set for both X and Y then a collision has taken place. It's working well so far.
I'm very happy as I've made good progess with the enemy code. I've created a routine that runs when the player changes a screen to draw the enemies for that screen, based on the screen number and lookup tables I have created. First, I disable sprites, draw the new screen, lookup the enemy data which includes 8k bank and offset, set MMU slot 0 to the 8k bank, copy the data to my enemy buffer, then enable sprites. The next step will be to integrate my player animation code into the enemy movement code.
I've added 2 extra bytes to each enemy's data to hold the animation timer and frame. This also means each enemy can start at it's own unique frame, if required. Enemy buffer size is now 300 bytes, 15 bytes each enemy. I'll need to make some adjustments to the enemy data lookup table to accomodate this.
Another update today and I can now animate enemies. Lots of testing to take place with this to make sure it works as it should then the next step will be to check if the player has collided with an enemy which I should be able to integrate into the enemy movement routine.
I've moved the enemy data to 8k banks and have created a lookup table with the 8k bank and offset for the relevant screen. I'll then perform a lookup when the player moves from one screen to another and pull the enemy data for that screen and copy it to the enemy buffer.
At the moment, the enemy data and screen data will support up to 100 screens with up to 20 enemies per screen. This is with me working in the confines of 1MB RAM so if the game needs to have more data stored I can look to squeeze more into 1MB though I do need to account for data such as music and sound effects. I could expand it meaning support would only be for 2MB machines, but more data could be stored.
I've just sorted the 9-bit values for the enemy movement so that they display correctly when they're at the edge of the screen. Next step now will be to look at enemy data per screen. Plan is to store the number of enemies per screen in a similar way I store the screen data.
I've managed to steal a few minutes today and am continuing my work on the enemy code. I have allocated a buffer for enemies that are currently on screen which will contain around 13 bytes per enemy. The buffer will be written to each time the player moves from one screen to another. Data per enemy will include, x, x from, x to, y, y from, y to, x direction, y direction, x speed, y speed, pattern from, pattern to and animation speed.
Further tinkering today has meant that I am utilising the index registers for enemy movement. The index registers are loaded with the enemy data for the current screen then each enemies parameters are obtained by a common offset for each meaning I only need add the amount of bytes for each enemy to move to the data for the next one. This has made it easier for me to draw several enemies to the screen, each with their own unique movement limits and speed. Next steps will be to set enemy data according to the screen the player is on.
I'm creating enemy code at the moment and am testing automatic movement for enemies between fixed points and with a fixed speed. It's working well so far. Lots more work to do here such as creating a table holding the enemy data for each screen including how many enemies there are for a particular screen, their starting position and direction, their movement limits, sprite patterns, how many frames of animation they have and their speed. Then will come collision detection with the player.
The player movement speed has been slowed down and I've added an animation timer to slow the speed of the animation down. The jump table has been slightly adjusted so you float a bit more. I've also made a couple of tweaks to the code for moving from one screen to another. Plenty more testing to do with that, but it's getting there.
After some tweaking I am happy with my screen code when moving from one screen to another. Now I just need to create some more screens to test that with. One of the next steps will be to create some enemy movement code.
The sprite data is now in the source file for the main character and I have loaded the first frame of animation successfully. Next steps will be to load the rest of the sprite data into the sprite patterns then create an animation routine.
Player sprite fully loaded in now and is animating when the player presses left or right, correctly cycling through all 8 frames of animation. Next step will be to slow the rate of animation down as it is currently too fast.
I've created a basic, 2-dimensional, 10x10, game map and can traverse it accordingly. I can specify the starting position on the map too. I will be extensively testing this to ensure there are no errors, for example making sure you can't go off the game map. I'll create a few more basic screens too to aid with this.
I have amended the screen drawing routine to use 1 MMU slot instead of mapping 1 layer 2 16k bank to $0000. The MMU slot is slot 1, meaning the ROM is getting paged out, and I will use slot 2, the other half of the ROM, for tilemap and collision data.
I have just created a screen in my NextBASIC screen editor and been able to include it in a NEX file to be drawn within seconds. Very happy with this as I can draw screens and test them out in a NEX file very quickly.
I've made a small lookup table of around 200 bytes (currently allowing up to 100 screens) which stores the 8k bank a screen's data is stored in and it's offset. This means I have written a routine that enables me to simply specify the screen number, 1,2,3,etc., for it to be drawn. The routine takes the screen number and uses the lookup table to obtain the relevant 8k bank the tilemap and attribute data is in. The tilemap and attribute data are then copied into a common MMU slot used by my main screen drawing routine.
Further tinkering today - I have now integrated my player input code into the main code with the screen drawing routine meaning I can now move the player around after I have called my screen-drawing routine. Next steps will be to create a basic game map using the screen numbers and move the player around it.
Today, I've been able to use my z80 editor to create a binary file that only holds the tiles and tilemap data. I've then been able to include this file when assembling the source code. This means that I can now have external data files which makes the source code a bit easier to manage and will also help me to automate the creation of projects in the future by creating files that contain common setup code, etc.
I've been testing with uploading data directly from CSpect to my server and it works very well. The plan with this is to add this functionality to my screen editor then I can directly upload the screens I design to be included in a NEX file.
After tinkering a bit more today I have integrated the upload code into my screen editor and have been able to save some screen data in CSpect (tilemap and attribute data for collision checking), upload it, and include it in a NEX file. Next steps will be to display it which will require some data reorganisation.
I'm now getting the hang of NEX files and have managed to create a source file that loads data, such as the tiles and tilemap, into a specified bank and then recall that data later on. This means I'm no longer assembling everything to the main memory and can now concentrate on data structures etc although one of the next steps will be to get the main player sprite data into my source file.
I have been experimenting with creating NEX files to aid in displaying a layer 2 tilemap in assembly as it appears that when I try to incorporate the assembly with BASIC for this purpose it causes memory errors. This means I have successfully created my first NEX file! It's just a basic file that displays the standard layer 2 palette, but it works without issue. Next steps will be to integrate my existing layer 2 tilemap code into this to display a full layer 2 tile-mapped screen.
I've managed to set part of layer 2 to an MMU slot and read/draw part of a tilemap which I'm very pleased about. This means that I've been able to draw 4 rows of 8x8 tiles at the top of the screen.
So far, this particular routine is about 200 bytes. All I need to do now is make a loop to run through the routine 6 times (each MMU slot is 8K, 8x6=48K, the size of a standard layer 2 screen).
I've been able to display a full row of tiles from a tile map in assembly so far. More work to be done as each MMU slot holds 8K of data, 4 rows of 8x8 tiles each slot, so will need 6 swaps in total to accommodate the 48K of a standard layer 2 screen, but it's a promising start.
I've managed to load in a tile sheet, in BASIC, and write a routine that displays a particular tile on the screen, in assembly. Now I need to work with that routine to display the tiles according to a tile map.
In preperation for using assembly to draw a screen in from tiles, instead of what I'm currently doing which is using the TILE command in NextBASIC, I have begun looking into using the MMU slots. So far I have been able to page out the ROM, page in a Layer 2 bank, write to it, then page the ROM back in. I'm paging the ROM out and back in again as I am using NextBASIC to facilitate testing my assembly code. Next steps will be to load in the tiles and a basic tilemap, page them in to MMU slots, page a layer 2 bank into an MMU slot and , finally, draw the tiles on screen. Then I can put together a routine which will draw a whole screen, by paging in the necessary banks at the required times.
Building on yesterday's code, I've created seperate routines to detect when the player is at the edge of a defined screen area. These routines are setup in such a way that all I need to do is add the relevant code for drawing in the new screen depending on which direction the player has exited the current screen.
Today, I've done some prep work in assembly to set screen limits to stop the player going off screen and also to facilitate moving from one screen to another.
I've been away for a few days and am just getting back into the swing of things. I've gone back to my screen editor and made it a bit more user-friendly. The current plan is to design a few basic screens, create a game map then allow the player to traverse it. I'll do this in BASIC initially, but will convert it to assembly when I'm happy with it. Then I'll look into the possibility of getting the sprite data into assembly and animating it in assembly as I'm currently doing this in BASIC.
I've made a new screen editor in BASIC which allows me to place tiles down on layer 2 as well as attributes on layer 0 (for collision checking) at the same time and I'm able to save and load both. I've tested this with the engine I have in assembly and it works well. It needs some extra features like being able to select the tile you're placing, but it works great for quickly plotting out a screen.
Some work done today in preparation for the game map code. The player sprite can exit the screen one side and appear the other. This also means I can easily add code in for moving from one screen to the next.
The current plan is to get a basic game map sorted and enemies placed on each screen, along with their relevant movement patterns. Initially, I will do this in NextBASIC. This will help me to translate it to assembly.
This is in BASIC at the moment although I will endeavour to convert as much as I can to assembly. The jump arc is not final, but gives you an idea of how it will look.
I've been sent some artwork and have made a sprite sheet out of it. I have provisionally tested the sprite animation in BASIC and it works very well. I will look into creating a custom palette for it soon. I have been looking into using Next registers to set sprite patterns and will utilise this so that will be one more thing that I should be able to do in assembly as opposed to NextBASIC.
While keeping data storage in mind, I have started work on a screen editor in NextBASIC. This doesn't really need to be in assembly as it is only for designing/mapping out screen data, although this may change in the future. The resulting data will then be added to the assembly code.
At the moment I can place the attributes for solid walls and platforms then easily return to the main loop to test it out. I also have basic save and load functions which only store one screen at present, but will be expanded so I can make game maps.
I have just got platforms working so you can jump up through them, but can't go down through them. This means there are now 2 main collision checks taking place: solid walls and platforms. It also means that all the main player movement code is done.
Next I will be looking into storing screen data, enemy data (including movement speed, direction etc.), sprite sheets, tiles, etc. All of this I'm doing in NextBASIC at the moment, but I want to get as much as I can into assembly.
And now I can successfully use the player x as a 9 bit value!
Next up is checking for platforms that the player can jump up through, but can't go down through.I've finished tweaking the fall routine and it works the way I want it to now. I can feed in any values to the fall table and it will work with any of them. Next up is the jump routine. Now that the fall routine is complete it should help me with the jump routine.
The code is just under 700 bytes currently, which includes the data for the jump/fall routines.
The values from the fall table are now in use so this means there is now gravity. I'm maintaining a fall pointer to say how far into the table the fall is and moving the player down the relevant number of pixels in the table. A few tweaks to make it perfect, but it works very well. Once this is done I will work on the jump table.
The jump and fall tables are now in place in assembly so the data is there. What I need to do now is use that data for the jump and fall routines accordingly.
I now have a basic fall routine in place whereby the player will fall at the current player speed until they land on a platform. All I need to do now is generate a fall table which I can then feed in when the player falls to better simulate gravity like I have already done in BASIC.
I've also gone through all the code and managed to shave about 50 bytes off due to doing the checks for platforms on layer 0 now. This means fewer checks are taking place, but still producing the same result.
I've finished the tweaks and it works the way I want it to now. Now I'm moving on to gravity with the jump/fall routines. Code is around 700 bytes so far so I'm quite pleased with how small it is.
In assembly I can now move in all directions and detect platforms and prevent movement in all directions. A lot of tweaking now to get it perfect, but the base is there. Once that is done I'll move on to gravity.
I can now move up and detect if a platform is in the way and prevent movement. While I'm not necessarily making a top- down engine, this will help when I implement the jump table.
In assembly I'm now merging the routines for checking for platforms to see if the player can move and then moving the player. At the moment this means the main game loop will be completely in assembly, which was my aim.
After this is done, I will move on to converting the jump/fall routines I have in BASIC to assembly.
I can detect input in assembly now. Only very basic, but I can build on it so looking promising to get even more of the engine in assembly.
And now I can move sprites with player input. Again, a lot more to do, but it's looking very good..
Player input workiing in all directions with error checking so it doesn't go off screen and I can set the player speed accordingly.
Been optimising my z80 and it runs very well for the platform detection. I have a better workflow now too.
I'll probably be adding player input next.
I've converted the collision detection to use layer 0 instead and it's much better. Left and right collisions already done. Top and bottom to do now.
And now I can detect pixels at the top and bottom of the sprite so that's all sides I can detect. Lots of tweaking now.
The conversion of the collision detection from BASIC to assembly is going well. I can now detect walls to the left and right of the player sprite.
Pixel detection in assembly when moving left is working. Still a long way to go, but that was one of the hard bits.
Plan now is to put all logic for the engine into assembly, which will include detecting solid walls and platforms. Might rewrite it to use layer 0 instead of layer 1 for attribute-checking. Means it will be easier to store the screen data (less data to store too) and then layer 1 (lo res) could be used for graphics too.