Jump to content
IGNORED

Spire of the Ancients (WIP)


SmittyB

Recommended Posts

Update 2020/05/28 - As you can see it looks a little different 4 years on.

0027.png.2ec57fe781c31237533b21fd5ec7d6d7.png

 

'lo all,

 

I've recently been working on a Dungeon Master-esque maze game in 7800 Basic with the intention of maybe turning it into a basic first person roguelike but I just flick between different projects and never finish anything.

 

Instead of letting it go to waste I thought that if I upload it here somebody can learn from it or use it as a starting point for another project.

 

For the sake of making something quickly all the walls are large banners rather than being made of tiles so it wastes a lot of space in memory and I've had to put the plot commands in subroutines as the closest wall graphics are too big for an IF statement to jump over the draw calls.

The best improvement would be to switch to using a tilemap for each wall to reuse graphics and save space for other wall graphics and/or monster/item graphics etc.

 

The HUD would also need a lot of adjusting to make it more efficient and I've not been able to get the text to work properly in the time that I was making this.

 

Hope somebody finds this helpful.

3D Maze.zip

post-27819-0-43870800-1472509746_thumb.png

post-27819-0-93762200-1472509750_thumb.png

 

 

 

 

  • Like 20
Link to comment
Share on other sites

Such a pretty job, SmittyB! Really impressive, and it fires up my imagination with the sorts of games the 7800 should have received BITD.

 

Don't sweat about bouncing around. It probably just mean you haven't found the right project. Before I committed to and finished my first 2600 game, I did the same thing for quite a while.

  • Like 4
Link to comment
Share on other sites

  • 3 weeks later...

Okay so since I first posted this thinking I'd never look at this again I've been spending a lot of time updating it.

I've started using tile maps for the graphics, the map(s) are 16*16, and I have static objects and enemies that can be removed with the left button.

I'm actually motivated to finish this and it's all your fault!

post-27819-0-61870500-1474141153_thumb.png

post-27819-0-68481400-1474141157_thumb.png

game.bas.bin

game.bas.a78

  • Like 14
Link to comment
Share on other sites

I wonder if somebody can help with this. A problem I keep running into is the plotchars / plotvalue statements in BASIC keep using every other character.

I've managed to fix nearly all of the cases of it so far as I found that 'set doublewide on' seems to do more than just setting the doublewide bit in the CTRL and SCTRL registers but I can't find what exactly.

By changing things around I found that statements like 'incmapfile' require doublewide to be set as it will be when the map is drawn, but changing it through assembly did nothing so I had to reorder the way I included data.

 

This has worked so far except for plotvalue. I'm using the same text graphics as my other single-width characters (that previously had the same problem) and I've tried using plotvalue before using 'set doublewide on', after, and also before and after where I'm changing it with assembly. What happens is that I try and plot the value $09 but the output is 'i' because that's the 18th character in my text. $99 becomes 'ii', $10 becomes '20' etc...

 

Just when I thought I had an idea of what's going on this happens. Of course it would also be useful to know exactly what 'set doublewide on' is doing in the background because I keep running afoul of it.

Link to comment
Share on other sites

We could wait for Rev to reply or we can dig into the assembly source and find instances like this in the plotvalue code! (just snipped out. there's extra code around/between them! ;))

     ifnconst DOUBLEWIDE ; multiply value by 2 for double-width
         lsr
     endif

     ifconst DOUBLEWIDE ; multiply value by 2 for double-width
         asl
     endif

I'm assuming the use of ifconst shows the assembly of the rom itself gets altered at compile time and doesn't change. So you're stuck with either-or after using set doublewide on. These are likely the cause of the issue you're experiencing.

  • Like 1
Link to comment
Share on other sites

Mord nailed it... "doublewide" enables compile-time code. As to what doublewide does additionally: twice as many bytes per character means character byte-offsets need to be twice as large. i.e. the 5th doublewide score digit is 10 bytes in. Maria still deals with byte offsets, even when doublewide characters are enabled.

 

You shouldn't need to enable doublewide when using maps with incmapfile, if you need to use singlewide text elsewhere. You just need to ensure you work in with byte-width tiles in tiled. e.g. for 160A, bytes are 4 pixels wide, so you need to use 4 pixel wide tiles.

 

Another alternative is to keep doublewide and just roll your own BCD character strings, using plotchar instead of plotvalue. The additional advantage to doing that is you can "bake" plotchar commands into the display by using "savescreen", and you just need to change the string memory in the main loop for updates, rather than doing a cycle-expensive plot command. To get maximum sprites on-screen, I use this technique in Salvo.

 

Many of us are impressed with what you've done so far, SmittyB. It looks really amazing! Please don't hesitate to post more on this or any other problems, and we'll help as best we can.

  • Like 4
Link to comment
Share on other sites

  • 3 weeks later...

I'll probably upload another build later because I've managed to get enemies randomly moving around the level. I've set a limit of 16 objects for now but with every new feature I add it's taking more frames to draw and it's becoming quite the flickering mess.

 

I'm going to go through and optimise what I can but are there any tricks I'm missing?

Is it quicker to draw a large image as a banner or a tilemap? I think drawing the closest walls is where most of my time is going.

Am I saving much time by skipping over consecutive if statements?

How much time is wasted as overhead for using subroutines?

 

At the moment I'm saving the HUD and using restorescreen at the start of each frame but I'm going to change this to save the whole screen, then use a flag to say whether or not to redraw the whole lot when something changes. I think this should make the flicker less frequent but heavier when it does happen for the time being.

  • Like 5
Link to comment
Share on other sites

> Is it quicker to draw a large image as a banner or a tilemap?

 

Actual time to plot... the banner is a bit quicker.

 

But you can plot a block of ram as characters, do a savescreen, and later updated the memory wit out any plot commands. That's a lot faster. (There's an example of this in the 7800 basic samples)

 

Just avoid multiple plots of characters over existing characters. Maria will run out of time to render them if you do that.

 

> Am I saving much time by skipping over consecutive if statements?

 

Some, not a lot. It depends on how many, of course.

 

> How much time is wasted as overhead for using subroutines?

 

Not a whole lot in the scheme of things. There's usually better ways to optimize.

 

In addition to the ram based characters I mentioned earlier, the other thing to do is ruthlessly separate your game logic from your screen updates. Any code with plot commands should be grouped together, and run last, right before the next drawscreen. That way your game logic runs during the visible screen.

 

The first plot command encountered causes a wait-until-screen-over operation, to avoid glitching.

 

If needed, in this sort of game you could even spend 2 or 3 frames on game and plot-prep logic, and do only the actual plot commands in the following frame.

  • Like 3
Link to comment
Share on other sites

Given the way the 7800's display isn't tile based I completely ignored that I could just do that. It works well for me because my screen is just made up of about 9 specific parts. I could plot individual maps for these then I only need to plot enemies and objects over the top.

 

I think doing it as separate maps would make it easier to copy each tilemap.

 

It's taking a lot to get my head around the 7800s way of drawing graphics over multiple frames.

  • Like 3
Link to comment
Share on other sites

Given the way the 7800's display isn't tile based I completely ignored that I could just do that. It works well for me because my screen is just made up of about 9 specific parts. I could plot individual maps for these then I only need to plot enemies and objects over the top.

 

I think doing it as separate maps would make it easier to copy each tilemap.

Sounds like a solid plan to me. :)

 

 

 

It's taking a lot to get my head around the 7800s way of drawing graphics over multiple frames.

Some comments around this, to hopefully help sort it out...

 

Drawing over multiple frames on the 7800 is problematic, without a double-buffering scheme. When each 1/60th of a second rolls around, Maria will stop the CPU cold, and it expects all of the display memory structures to be complete. 7800basic doesn't support double-buffering (along with many other commercial games) because it would eat up much of the stock RAM. If 7800basic does support double-buffering in the future, it will require on-cart or XM RAM.

 

So what we're left with is the program leaving the display structures alone (ie. the structures modified by the plot commands) over as many frames as you need to prepare for plotting, and then plotting everything all at once before the next frame comes around.

 

A regular 7800basic optimized loop looks something like:

mainloop
 [game logic]
 restorescreen
 [plot commands]
 drawscreen
 goto mainloop

If your game needs more frames, then it looks like this:

mainloop
 [game logic part 1]
 drawscreen
 [game logic part 2]
 restorescreen
 [plot commands]
 drawscreen
 goto mainloop

...none of this applies to RAM based characters that are already plotted (ie. they're already in Maria's display structures). Those you can change whenever you like.

  • Like 3
Link to comment
Share on other sites

  • 5 weeks later...

A small update to show the newer HUD that gives the map name, stats, and equipped items.

 

I haven't done much in a while because the thought of drawing a lot of new graphics has been keeping me away. It's now possible to attack the monsters even if they don't attack back and you can now move onto a second map by finding the door but you have to be right next to it to see it as I haven't done any extra sizes for it so far.

 

Drawing the walls is now more efficient as it's all done by changing tile maps but the new HUD still needs a lot of improvement. The map name, the stat values, the items, and the compass N are still drawn on top of a tile map underneath. Similarly each frame of the attack animation is just one big banner stuck in the centre of the screen. Hopefully reducing the amount of things being drawn in the HUD will get rid of the black areas but I'm guessing it's also partly to do with not fully lining up with the zones they're in.

 

Is there any way with assembly to modify the display lists on the fly? Something I've been thinking about is that if it were possible I could change the palette of my tile maps to give different walls different colours instead of a single palette for the map.

post-27819-0-77520600-1478387198_thumb.png

game.bas.a78

game.bas.bin

game.bas

  • Like 6
Link to comment
Share on other sites

Is there any way with assembly to modify the display lists on the fly? Something I've been thinking about is that if it were possible I could change the palette of my tile maps to give different walls different colours instead of a single palette for the map.

Are you using the "tiled" app and map files? If so, you can you define a "default" palette for any group of tiles that you import with incgraphic, and then plotmapfile will use that palette for the tiles when it plots them. This is Atarius Maximus drew land and sea tiles in his Adventure Demo. There are notes on it in the manual, under the incgraphic and plotmapfile entries.

 

If yo really want to reach into the display lists we could work something out, but anything we hack together may be subject to change when those bits of 7800basic are reworked.

Link to comment
Share on other sites

I do use tiled and have made good use of it with 7800 basic but it would mean going back to redrawing the walls each frame instead of modifying the tile maps I'm using.

 

If basic predictably generates labels to the display list headers I can change the palettes on the fly without having to recreate the maps or duplicating graphics. I could probably look through the assembly and check but I'm not at my computer.

Link to comment
Share on other sites

I do use tiled and have made good use of it with 7800 basic but it would mean going back to redrawing the walls each frame instead of modifying the tile maps I'm using.

 

If basic predictably generates labels to the display list headers I can change the palettes on the fly without having to recreate the maps or duplicating graphics. I could probably look through the assembly and check but I'm not at my computer.

They don't have labels as such. There's a hi and lo byte look-up-table pointing to each zone's DL. This table is used to setup indirect access the actual memory for a given zone's DL. The plotsprite function in std_routines.asm can be looked at for an example.

 

All of that said, the palettes aren't assigned per-byte, they're assigned per 5-byte DL entry. Plotmapfile doesn't create a unique DL entry for each byte - the 7800 doesn't have enough memory for that, and even if it did it would be very wasteful of Maria cycles. Instead plotmapfile lumps together characters with common palettes, and creates a single DL entry for each.

 

So using existing DL entries, you won't be able to modify a few characters mid-screen to use a unique palette. You'd need to rebuild the DL entries to do that.

Link to comment
Share on other sites

It would be changing all the characters under a given dl that I'd be interested in. The way my screen is arranged I have 2 character maps for the HUD, and 7 more maps that correspond to the 7 possible walls that can be seen at once. At the moment the wall maps all use palette 7 and I'd be aiming to change the palette designation for each independently without having to create new dls and slow things down.

I guessed that the plotmapfile statement worked as you said it does. I'll have to play around with the assembly to see if I can change the header on each of the dls that make up each map. I don't need to be able to do this for the game but I figured if I could make it work it would be a nice touch and allow for more varied levels.

 

I have a habit of playing games and seeing where the developers missed a trick or could have improved things which doesn't help with the perfectionism. I should probably implement a basic win/lose condition first so it can be considered a game then build on that.

Link to comment
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.
Note: Your post will require moderator approval before it will be visible.

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...