Jump to content
SmittyB

Spire of the Ancients (WIP)

Recommended Posts

I've started playing around with the tracker to add some basic music / jingles but I've noticed that in some situations notes are being skipped. For examples I have a simple 5 note chime that plays perfectly in PAL, but in NTSC, or if I have a longer instrument, or if I add a second channel it starts dropping notes. I'll keep playing around with it to see what I can find.

There's only 2 voices, so if they're both currently occupied, then either the new sound or one of the currently playing sounds has to be dropped... you can tweak the sound priority in the instrument definitions to make the compromise you prefer. In this case it sounds like you should lower the chime instrument priority, so it can be interrupted sooner. (the driver decreases the priority of any playing sound over time, exactly to avoid a long playing sound doesn't hog the channel, unless you override that by setting the priority to a large value.)

 

In the case of the Salvo theme, drums have priority=0 (only playing when there's a free channel, and giving up the channel to any new sound), and other instruments have varying priority. Arpeggios use an instrument with very low priority too, because you'd never notice some of those notes drop out, when the melody is playing over top.

 

It's also useful to use syncopation in your compositions, since that can avoid the melody and harmony competing for the same beat. There's a similar tip for making arpeggios that play a rest as the first note in the TIA Apreggio Tips doc.

  • Like 1

Share this post


Link to post
Share on other sites

Just bumping the priority from 0 to 1 did the trick, thanks. I'll need to keep the priority in mind if I want my secret chime to play over the sfx.

  • Like 2

Share this post


Link to post
Share on other sites

Quick update. I've got distance based sound working. I wasn't happy with the line of sight based sound because it just felt far too unnatural to have something suddenly appear behind a corner which couldn't be heard before. I'll have to tweak the distances but the way it's working at the moment is to find the distance between the object and the player, then play either a loud, mid, or quiet version of a sound based on that.

  • Like 5

Share this post


Link to post
Share on other sites

Another update (I'm finding it easier and more motivating to keep track of changes this way).

Maps are no longer limited to a 16*16 square and can have any width and height as long as they're 256 tiles or less in total. This means small rooms take up significantly less space. I had built this from the start but never really enabled it until now.

I have also optimised the wall drawing with assembly, saving over 1K of ROM in the process. There's not much in the way of an obvious speed improvement but the extra space is still very nice and it should help when I get to optimising some of the other big lists.

I'm also thinking of leaving out saving to HSC or Savekey in favour of a password (which I wanted to implement anyway) because I have no way of personally testing it and it wouldn't really work juggling a Savekey with the keypad or second joystick.

  • Like 5

Share this post


Link to post
Share on other sites

Another update (I'm finding it easier and more motivating to keep track of changes this way).

Maps are no longer limited to a 16*16 square and can have any width and height as long as they're 256 tiles or less in total. This means small rooms take up significantly less space. I had built this from the start but never really enabled it until now.

I have also optimised the wall drawing with assembly, saving over 1K of ROM in the process. There's not much in the way of an obvious speed improvement but the extra space is still very nice and it should help when I get to optimising some of the other big lists.

I'm also thinking of leaving out saving to HSC or Savekey in favour of a password (which I wanted to implement anyway) because I have no way of personally testing it and it wouldn't really work juggling a Savekey with the keypad or second joystick.

If you need a tester...i have savekey,Atarivox and HSC

greetings Walter

Share this post


Link to post
Share on other sites

I've completely rewritten the item selection in assembly and fixed quite a few bugs with it. It now works as I had originally planned so that you can't hold the same item in both hands, and if you try and switch to and item you're already holding then it just goes to the next. As part of this cycling back through the item list works too when using a keypad or a second joystick. When using a second joystick it's now set to have up/down as the next/previous left item and right/left as the next/previous right item which I think is a scheme that works nicely with any joystick and might even be better than a keypad for those with nifty twin-stick setups.

 

I have decided to keep HSC / Savekey support and I'm currently elbow deep in writing the password system which I already have a bare bones working example of. The idea is that when you go back to the title screen with a game over or pause+reset the game it will default to the 'continue' option which will already have the password listed so you don't have to keep entering it in one sitting. The HSC / Savekey will just save the password so that when the player boots up the game and chooses continue it's already entered. I'm still figuring out a good password format that doesn't require entering 23 characters of 32 symbols but most of that is for keeping track of what the player has in their inventory and what they've already picked up around the game to prevent things like stat ups from respawning when the player re-enters a room.

 

Additionally, if I have the space at the end of everything I've decided I want to try and implement a basic random map generator for something to do when the main game is finished, even if it's just a grid of random predefined room shapes. I realised rather selfishly that when it's all finished I won't get the full enjoyment out of it as I'll know where everything is and what to do so a random map would help with that.

 

I keep looking at NES dungeon crawlers and thinking it would have been so much easier to stick with their simplistic graphics and random encounters. Then I remember that Dungeon Master was groundbreaking in 1987 for being realtime and I'm doing something similar within the limitations that were available to a console intended to release in 1984 (excluding the huge advantage of emulators and 7800BASIC to work with).

  • Like 3

Share this post


Link to post
Share on other sites

I keep looking at NES dungeon crawlers and thinking it would have been so much easier to stick with their simplistic graphics and random encounters. Then I remember that Dungeon Master was groundbreaking in 1987 for being realtime and I'm doing something similar within the limitations that were available to a console intended to release in 1984 (excluding the huge advantage of emulators and 7800BASIC to work with).

 

The NES is technically the older system, having been in market in Japan in 1983 already while MARIA was still in development.

Share this post


Link to post
Share on other sites

I haven't been able to make a lot of progress recently but what I have been able to do is:

Refine the keypad code to be a little nicer

Tidy the title screen so the start / continue options appear in the same place as my credit after pressing a button once

Free up yet more ROM for actual content

Add extra pickups including the stat increases

Map out a few new areas

 

I hope to get more done in the next week including modifying the enemy 'look' code for playing sounds at different volumes based on distance. To simplify things I'm going to have walls block sound so that like line of sight I only need to check 4 directions and not a whole area.

 

What are your current plans for the keypad in the game?

Share this post


Link to post
Share on other sites

What are your current plans for the keypad in the game?

The keypad can be used as an optional second controller to more easily select items and pause the game compared to using the console switches.

 

At the moment the only buttons defined for the keypad are 'next left item', 'next right item', 'previous left item', 'previous right item', and 'pause'.

Where it makes sense I'll add shortcuts to select specific useful items in the players inventory and use a difficulty switch to select which hand they go to.

As I add things I'll probably keep adjusting the button layout to get something that feels right because I don't want to add something to every button and find that it's awkward to find what you want in the middle of the action.

Share this post


Link to post
Share on other sites

The keypad can be used as an optional second controller to more easily select items and pause the game compared to using the console switches.

 

At the moment the only buttons defined for the keypad are 'next left item', 'next right item', 'previous left item', 'previous right item', and 'pause'.

Where it makes sense I'll add shortcuts to select specific useful items in the players inventory and use a difficulty switch to select which hand they go to.

As I add things I'll probably keep adjusting the button layout to get something that feels right because I don't want to add something to every button and find that it's awkward to find what you want in the middle of the action.

 

Instead of the Difficulty Switches, perhaps * = Left Hand and # = Right Hand could be utilized instead on the Keypad?

 

This way maybe allowing just a joystick as an optional second controller instead of console switches could also be a possibility.

 

For example:

Next Left Item = Left

Next Right Item = Right

Previous Left Item = Up

Previous Right Item = Down

Left Hand Select = Button 1

Right Hand Select = Button 2

 

It could be simplified with just a second joystick while also freeing functions:

 

Cycle Through Left Items = Left

Cycle Through Right Items = Right

Left Hand Select = Button 1

Right Hand Select = Button 2

 

Up and Down can be not assigned to any task for the time being.

 

The only thing excluded at this point is "pause", which of course can be performed on the console itself anyhow.

Share this post


Link to post
Share on other sites

sounds good...do not let us wait too long with a playable level

I'll try not to.

Thing is there's so much I want to add that would make levels a bit more interesting than a mostly static maze with a few slimes in it.

I've been planning how Dungeon Master style complex mechanisms will work and it means a much better experience while only using my existing system of objects, no huge rewrites. The downside is that at the moment linking objects together means a lot of manual work and changes aren't easy to test. I'm thinking I'll need to write a basic map editor that can spit out maps with linked objects in my chosen format. If I do then I can easily crank out new maps as needed, maybe to the point where I can make versions with different maps.

  • Like 1

Share this post


Link to post
Share on other sites

Trebor, the difficulty switch idea is only for the shortcuts that quickly select a specific item so that the player can say "I prefer mainly using button 1 so I'll select button 2 as my 'off hand' where quick items go when selected" which isn't something that would change during a game. An example being if the player is losing a fight and they quickly need to restore their health they can press a shortcut key on the keypad to select a health potion or spell and it will go to their off hand instead of swapping out their sword for it.

 

I suppose it would be simple to put a toggle key on the keypad but then I need an indication on screen for which hand is the off hand and it would only ever be relevant for somebody using the keypad.

 

As for the second joystick the current scheme is just that up and down select the left item, and left and right select the right item. I think it works well without getting too complicated.

  • Like 2

Share this post


Link to post
Share on other sites

I'm working to get you all a short playable demo of the puzzle system and I may be able to give you something this weekend at the earliest but no promises.

 

I said I might need to write a map editor but as I appear to have completely forgotten how to write anything in C++ I've instead decided to simplify a few things so now a full 256 byte tile map is compressed into 32 bytes, and instead of creating objects from the map data I'll have a separate object list where I can manually set the type, location, special parameters of all objects.

This way if I need to move things around I can just change the location without having to worry about linking things back together with new IDs.

  • Like 2

Share this post


Link to post
Share on other sites

I'm working to get you all a short playable demo of the puzzle system and I may be able to give you something this weekend at the earliest but no promises.

 

I said I might need to write a map editor but as I appear to have completely forgotten how to write anything in C++ I've instead decided to simplify a few things so now a full 256 byte tile map is compressed into 32 bytes, and instead of creating objects from the map data I'll have a separate object list where I can manually set the type, location, special parameters of all objects.

This way if I need to move things around I can just change the location without having to worry about linking things back together with new IDs.

 

Maybe you could ask Jwierer about an editor...he did many

7800 editors in the past.

greetings Walter

Share this post


Link to post
Share on other sites

Unfortunately no demo this weekend. The new map format works really well, but there's a bug in the way objects are now set up that is throwing everything off and the cause is eluding me. There's also an unrelated bug I found where things aren't consistently visible in the zeroth location. I'm not too worried about the invisible object bug because a workaround would be to always have that location as a wall.

  • Like 1

Share this post


Link to post
Share on other sites

I thought I'd post some code in case someone here can help with this bug. I've managed to work around it by adding a 4 byte offset but as the code is still only reading 80 bytes of data it means object 15 doesn't load. Interestingly I'm not directly specifying 80 bytes of data, just incrementing temp8 each time a byte is loaded until temp9 is incremented to 16, meaning objects 0 to 15 should be in memory. I could rewrite the loop and just keep going until 84 bytes have been read but I want to understand what's happening here instead.

	lda #0
	sta temp8
	sta temp9
.getDataLoop
	LDX temp8
	LDA MapCondensedObjectDef,x
	LDX temp9
	STA objectID,x
	inc temp8
	
	LDX temp8
	LDA MapCondensedObjectDef,x
	LDX temp9
	STA objectLocation,x
	inc temp8
	
	LDX temp8
	LDA MapCondensedObjectDef,x
	LDX temp9
	STA objectParam1,x
	inc temp8
	
	LDX temp8
	LDA MapCondensedObjectDef,x
	LDX temp9
	STA objectParam2,x
	inc temp8
	
	LDX temp8
	LDA MapCondensedObjectDef,x
	LDX temp9
	STA objectParam3,x
	inc temp8
	
	inc temp9
end
	if temp9 <16 then goto getDataLoop

The data is currently in ROM but will be copied to and loaded from RAM when this all works

	data MapCondensedObjectDef
	0,0,0,0 ;4 byte offset should not exist
	253,16,0,19,0 ;Object 0
	2,2,0,0,0 ;Object 1
	0,0,0,0,0 ;Object 2
	0,0,0,0,0 ;Object 3
	0,0,0,0,0 ;Object 4
	0,0,0,0,0 ;Object 5
	0,0,0,0,0 ;Object 6
	0,0,0,0,0 ;Object 7
	0,0,0,0,0 ;Object 8
	0,0,0,0,0 ;Object 9
	0,0,0,0,0 ;Object 10
	0,0,0,0,0 ;Object 11
	0,0,0,0,0 ;Object 12
	0,0,0,0,0 ;Object 13
	1,240,0,0,0 ;Object 14
	1,1,0,0,0 ;Object 15
end

Share this post


Link to post
Share on other sites

Nothing jumps out immediately... you aren't using this in an interrupt, are you? Or using temp9 in an interrupt?

Share this post


Link to post
Share on other sites

I'm not using it in an interrupt but I'm using double buffering so I'm wondering if my topscreen routine is causing the trouble. I have tried using other temp variables in place of temp8 with no luck but at this point if I can't see anything in topscreen then I'll rewrite the loop and forget about it.

Share this post


Link to post
Share on other sites

I'm not using it in an interrupt but I'm using double buffering so I'm wondering if my topscreen routine is causing the trouble. I have tried using other temp variables in place of temp8 with no luck but at this point if I can't see anything in topscreen then I'll rewrite the loop and forget about it.

Just to clarify, does your topscreen routine use any temp* variables? If so, replace them with the inttemp* variables.

Share this post


Link to post
Share on other sites

Also, as a general 6502 assembly tip, storing structured data serially is usually a mistake. If you peel off each type of data into it's own individual look up table, the assembly to parse it becomes a lot simpler and faster. As a bonus you can deal with up to 256 objects (the code below does up to 128), and it's easier to add/remove object data types...

 

 asm
  ldx #15
LoadObjectsFromRomLoop
  LDA MapCondensedObjectID,x
  STA objectID,x
  LDA MapCondensedObjectLocation,x
  STA objectLocation,x
  LDA MapCondensedObjectParam1,x
  STA objectParam1,x
  LDA MapCondensedObjectParam2,x
  STA objectParam2,x
  LDA MapCondensedObjectParam3,x
  STA objectParam3,x
  dex
  bpl LoadObjectsFromRomLoop
  jmp SkipObjectTables
MapCondensedObjectID
  .byte 253, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1
MapCondensedObjectLocation
 .byte 16, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240, 1
MapCondensedObjectParam1
 .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
MapCondensedObjectParam2
 .byte 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
MapCondensedObjectParam3
 .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
SkipObjectTables
end

No reason why I couldn't have used 7800basic data tables, but since you already broke out the assembly, this saves a few bytes of padding. In the same vein, there are further optimizations that could be applied to my code, but I think it serves for illustrative and flexibility purposes.

 

If you want to restore some visual structure to your object data, I'd recommend storing the data values in hex representation, as it's easier to keep fixed width. That way you can still easily read an object's data by looking at it's vertical column. You can even add a header comment in the style of "; 0 1 2 3 [...]" to easily pick out which column belongs to which object.

 

But please do ensure that your topscreenroutine is free of temps. Even if you eliminate the use of temps in this particular routine, using the temps during interrupts can have randomish negative effects on other 7800basic functions that use them.

  • Like 3

Share this post


Link to post
Share on other sites

Looks like I don't use temp variables at all in topscreenroutine so I guess I'll chalk this one up to aliens with nothing better to do than to break my code.

As for the data structure, I know it's nowhere near efficient and I do have better structure everywhere else but I decided to deliberately do it this way for readability and ease of editing. It's only run during a map change so at most an additional frame wouldn't make a difference. However, thinking about it some more I'll just go with the straightforward structure here too, it will only take a few seconds longer to make changes to the object list.

  • Like 2

Share this post


Link to post
Share on other sites

...and now all working hassle-free with the rewrite. Now to make it load the list from RAM, clean it up, add some objects, make some maps, and give it a whirl.

  • Like 1

Share this post


Link to post
Share on other sites

...and now all working hassle-free with the rewrite. Now to make it load the list from RAM, clean it up, add some objects, make some maps, and give it a whirl.

And a full playing level for testing

Share this post


Link to post
Share on other sites

It's not the update I was hoping for but instead of keeping you waiting longer here's something at least. I haven't been able to make as much progress as I wanted as I've been working on removing / replacing objects where a lot of the code is shared or can be reworked as part of the complex mechanisms system.

An example being I had about 4 different pressure plate objects before but now there's only 1 that changes the state of linked objects. So instead of a pressure plate to remove a wall it can be set to change the state of a 'ChangeWall' object, while simultaneously igniting a torch by changing its state to 1, and playing the secret chime through a 'PlaySound' object.

 

I haven't tested the keypad since making a lot of changes so I'm not sure if it's currently working or if it's broken again. Also it might spontaneously pause itself because for some reason on my 7800 it likes to interpret no second controller as as the 11th key which I might have mapped to pause.

SotA.a78

SotA.bin

  • Like 3

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...