Jump to content
IGNORED

Chase


Recommended Posts

6 minutes ago, Lillapojkenpåön said:

So the best would be if everything was sprites? Mhm.. here I thought I was being smart avoiding using sprites as much as possible.

There's no hard and fast rule here, but rather some finer grained rules you need to consider for a given game design.

 

If your character graphics didn't change palettes so very frequently, they'd win out over sprites-as-tiles. Character objects have a higher up-front cost, but due to the dynamic nature of character strings, one single character object can manage a bunch of dynamic graphics. To do the same dynamic thing with sprites-as-tiles requires a bunch of sprite objects, and while sprite objects are cheaper than character objects, replacing one character object with a bunch of sprite objects will be a loss.

 

So much of this depends on the game design. Arkanoid and Millie&Molly require arbitrary palettes on any object in the game "grid" of objects, so using sprites is a no brainer there. I think the same is probably true here, but it's your call on how attached you are to the alternating palettes.

 

 

6 minutes ago, Lillapojkenpåön said:

I wonder if instead of this..

 

   y = (playerY - screenYoffset) / tileHeight

   x = playerX / tileWidth

   charValue = peekchar( tilemap, x, y, 20, 27 ) ; top left

   if charValue > bgTile then...

 

..this would work for collisions with the maze?

 

   y = (playerY - screenYoffset) & 240

   x = playerX / tileWidth

   temp5 = x + y

   if collisionMap[temp5] then...

 

The problem is that you have more than 256 characters in collisionMap. temp5 is only a byte (0-255) and array lookups are limited to 256 bytes max. It's an efficiency thing.

 

But you can use peekchar with your collisionMap array if you like. Matt has an example of that in his 7800basic tips, tricks, and examples thread.

 

 

 

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

7 minutes ago, RevEng said:

There's no hard and fast rule here, but rather some finer grained rules you need to consider for a given game design.

Got it.

7 minutes ago, RevEng said:

 

The problem is that you have more than 256 characters in collisionMap. temp5 is only a byte (0-255) and array lookups are limited to 256 bytes max. It's an efficiency thing.

 

But you can use peekchar with your collisionMap array if you like. Matt has an example of that in his 7800basic tips, tricks, and examples thread.

 

 

 

Yeah I realized and changed it before you replied, but the peekchar usage is awesome!

  • Like 1
Link to comment
Share on other sites

Ok, I got a display using only sprites instead, but how do I change it during gameplay?

Do I jump to a routine that clearscreen, update entire screen and savescreen again?

 

Or how do I remove or change a sprite that has been plotted without just adding sprites on top of sprites, or is that ok?

Edited by Lillapojkenpåön
Link to comment
Share on other sites

1 hour ago, RevEng said:

Clearing and redrawing will be too slow. Check out the under the hood demo, which has easy'ish assembly routines to update the Nth plotted sprite in any given zone.

Ah, that's usefull for replacing one tile at a time, but if I wanted all the dots to bounce, is there no other way than to make a nested for loop, look up every tile, and if it's a dot change it? Seems like it would take alot of time? how much time do you have for logic on the 7800 compared to 2600 btw?

 

And I'm also wondering if since the dot tiles use the same palette, if it would be better to keep them as characters and just use sprites for the palette changing maze tiles?

You have allready mentioned that as one suggestion, but mentioned it could lead to dma problems when adding more enemy sprites or more complex levels, but then you also said this

22 hours ago, RevEng said:

If your character graphics didn't change palettes so very frequently, they'd win out over sprites-as-tiles.

So I don't know what's best, I don't think I will add more than one or two more enemies.

I'm gonna experiment with the hybrid approach.

Link to comment
Share on other sites

5 hours ago, Lillapojkenpåön said:

Ah, that's usefull for replacing one tile at a time, but if I wanted all the dots to bounce, is there no other way than to make a nested for loop, look up every tile, and if it's a dot change it? Seems like it would take alot of time? how much time do you have for logic on the 7800 compared to 2600 btw?

Yeah, it would use a lot of time done that way, but these sorts of animations don't generally need to happen every frame, so you just do one or two rows in any given frame. Millie&Molly does that to animate the monsters, and Arkanoid does it to animate metal bricks. Even if you go back to characters for the dots, I'd still recommend splitting the updates up over frames, since iterating over X times Y things is expensive. I do the same in Salvo for when you lose all of the humanoids and the grid disappears.

 

On cycles...

 

Counting how many cycles the 7800 has is a bit less cut and dried than on the 2600. Typically the 7800 has a buttload more cycles than the 2600 because your game logic can run during the visible screen on the 7800, but on the 2600 the 6502 is completely tied up with the display kernel. The exact number depends on how much time Maria is stealing away from the 6502 - i.e. how complex your display is, from top to bottom.

 

To give you ballpark numbers, without taking Maria DMA into account, 7800basic has about 22000 cycles available during the visible screen, and about 8000 cycles outside the visible display during which plot* commands can execute. Even if you lose half of those cycles to Maria DMA (which would be a fairly complex display, top to bottom) that still leaves you with 11000 cycles per frame of game logic, apart from plot* commands. bB runs in overscan, and depending on the kernel gives you about 2398 (DPC+) to 2710 (standard) cycles.

 

So I think ballparking 4x logic time in 7800basic vs bB is a fair starting point.

 

Since the game logic runs during the visible screen, you can get a better idea of how much time any particular routine consumes, by changing the background color before and after the routine. You'll see on the screen exactly how much of the visible screen time is being used by the routine.

 

5 hours ago, Lillapojkenpåön said:

I'm gonna experiment with the hybrid approach.

For sure. Experimenting with a given approach, and throwing as many game elements at it as you need, is highly recommended. Then check it out in a DMA accurate emulator and/or real hardware.

 

 

 

  • Thanks 1
Link to comment
Share on other sites

The hybrid solution couldn't draw the last character in some zones when I made level 5, the biggest level in the demo.

To bad since I made a pretty dope level loading loop that plotted both sprites and characters from the tiled map.

 incgraphic tiles0.png 160A 0 1 2 3 0 rem empty

 incgraphic tiles1.png 160A 0 1 2 3 2 rem dot

 incgraphic tiles2.png 160A 0 1 2 3 0 rem blue tile

 incgraphic tiles3.png 160A 0 1 2 3 1 rem purple tile



 characterset tiles1

 incmapfile level5_offset.tmx    ; contains both sprites and characters to plot

 dim tileMap = $2200 



  memcpy tileMap level5_offset 208     ;copy tilemap to RAM



 const _emptyTile = #<(tiles0+0)

 const _dot           = #<(tiles1+0)

 const _mazeTile1 = #<(tiles2+0)

 const _mazeTile2 = #<(tiles3+0)



 const screenYoffset = 16

 const screenXoffset = 16





 clearscreen

 for tileMapY = 0 to 12 ; 13 horisontal rows

     for tileMapX = 0 to 15 ; 16 vertical columns



        charValue = peekchar( tileMap, tileMapX, tileMapY, 16, 13 )

        spriteTileX = tileMapX * 8 + screenXoffset    ; convert character column to pixel x pos

        spriteTileY = tileMapY * 16 + screenYoffset    ; convert character row to pixel y pos

        ; plot tiles from tiled map as sprites

        if charValue = _mazeTile1 then plotsprite tiles2 0 spriteTileX spriteTileY 0 1

        if charValue = _mazeTile2 then plotsprite tiles3 1 spriteTileX spriteTileY 0 1



        ; remove those tiles from tiled map

        if charValue <> _dot then pokechar tileMap tileMapX tileMapY 16 13 _emptyTile



     next

 next



  ; plot remaining dot characters

  plotmapfile level5_offset.tmx tileMap screenXoffset 1 16 13

 savescreen

 

All sprites works so far, gonna test how many more sprites I can add.

 

  • Like 1
Link to comment
Share on other sites

Hi @Lillapojkenpåön

 

Been following along with interest - Mike has outlined most of the stuff I did with Millie & Molly and Arkanoid already but here is a little more background.  With the animated tiles in M&M the whole tile gets replaced where with Chase is it appears you are laying out a background tile and then overlaying that with the dot? (have I got that right?? - if that's the case I can see why you would be running out of render time). M&M is relatively simple as the tiles were 12x24 so the screen is a grid of 14*9 - the animations were able to be validated over 2 frames (even one was fine TBH).  Arkanoid is a little different as the tiles are 12*8 so that made the game grid area something like 11x24 and animating those takes far more frames - maybe 4-5 frames? I just use a rolling update to do 3-4 rows each frame and it just cycles in the background.

 

With Mike's under to hood sprite process you don't use double-buffer as essentially pointers are updated instead. A couple of levels in M&M can have up to 50 tiles animating using this process - there would have been no other way for sure.  If the dot in incorporated into the tile you may have a good shot (obviously tile colors will be limited and 160B might push you over the edge). Overlaying the player/enemy should be be ok though (M&M overlays the player sprites). 

 

 

 

 

  • Thanks 1
Link to comment
Share on other sites

Man that's some unusual tilesizes you got ? I played through the entire millie & molly demo but I just enjoyed the game so I'm gonna have to do it again and see what you're doing, I really wanted to keep playing when the demo ended btw☹️

 

The background pattern and the dot is one tile, when I animated them before with characters it was pretty easy, I just copied the tiles to ram and set the charbase high byte thingy to look for them there, the low byte is in the tiled map table, so nothing is changed in the map itself, just at the location it looks for the tile I originally used when making the map in tiled, I think I just copy pasted the code from SmittyB. I could maybe just had two blocks with the same tiles except for that one and switched between them, that would have been really fast. I'm looking forward to trying the underthehood stuff when I get it to work.

 

13 hours ago, RevEng said:

Clearing and redrawing will be too slow. Check out the under the hood demo, which has easy'ish assembly routines to update the Nth plotted sprite in any given zone.

Is there something in the assembly that doesn't like that my screenheight is 224? I can get the player x and y position conversion right by doing some unexplainable +1 and -2, but it changes the tile two columns to the right when I'm on the top and bottom row? 

 

My radioclock just started playing music, 06:30, time to give up.

 

  • Like 1
Link to comment
Share on other sites

If you're using double buffering still, that might be the problem. (it's not designed for it)

 

Otherwise, it should work with any screen height, but it's not really officially supported, so not deeply tested with all of the options. If it's not working for you, without double buffering, let me know.

Link to comment
Share on other sites

2 hours ago, Lillapojkenpåön said:

I checked it out but I didn't understand much, I don't even know what DMA or a DMA hole is?

 

It looks like using direct mode for everything solves your problem, so my apologies for complicating things.

 

If you're curious about those terms: DMA is how MARIA, the 7800's graphics chip, reads the graphics headers and data from memory. DMA holes have to do with how MARIA reads objects that are not aligned to zones — a DMA hole is an area in the same zone as an object but above the top or below the bottom of the object.

 

  • Thanks 1
Link to comment
Share on other sites

Thank for the explanation. I certainly feel the under the hood method could definitely work well for this type of game if you spread the tile animations over a few frames. If I get a chance this week I'll try and put something together using the UTH code.

 

Oh the tiles in M&M are based on the c64 sprites which are 24x21. As they are colored double wide that converts best to 12x24 in 7800 land and they keep a good aspect ratio. 

  • Like 2
Link to comment
Share on other sites

10 hours ago, RevEng said:

If you're using double buffering still, that might be the problem. (it's not designed for it)

 

Otherwise, it should work with any screen height, but it's not really officially supported, so not deeply tested with all of the options. If it's not working for you, without double buffering, let me know.

I found the cause, if you look at my playfield row 2 and 12, I'm not plotting anything from the left before the maze tiles, so the dl index must start from the first thing you plott rather than from the edge of the screen, if I plot emty sprites everywhere where there's nothing it works as i expected it to, I tried just plotting column zero with empty tiles but doesn't work, you have to fill in a square area for it to work the same on each row.

  • Like 2
Link to comment
Share on other sites

I was just having a quick poke around and have a couple of thoughts:

  • Could you try 16 zone height tiles (knowing that bring difficulties with displaying text ?). The main bonus this brings is it might help the DL out and also reduce the validations required to scan the tilemap (saying that peekchar is very optimized).
  • The number of palette changes required between each tile is having the effect on the render time especially the larger the level gets (changing to a 16 zone might help also as it will have a 2x reduction on this?? 2x8 vs 1x16)
  • Plotvalue is extremely costly and is the cause of the slowdowns in level 3.  Mike's quick score technique is a great replacement (made a big difference for Arkanoid!!).

Give this a try now:

  • Rem out your plotvalues on the scorebar each update
  • Change all the tilemap graphics to use the same palette ie. 2

The under the hood process would probably require storing the maps differently as the level needs to be manually built with plotsprite so using data tables is very efficient (my large data table > 256 tip is a reasonable approximation on how I did my levels in M&M and Arkanoid - I used a program called Pyxel Edit to dump the maps out to data).  It will probably suffer from similar palette DL issues, would simplify validation and map updates but have a little cost updating the dots vs your efficient char replacement.

 

Hopefully that might help in some way in working out how to keep moving forward - let me know how you go!

 

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

The new version I made this weekend uses zoneheight 16 instead, 

It also uses only sprites now, and Tiled outputs a data table that I'm using allmost exactly like your pyxel table and peekchar

 

I think I've found the perfect balance, I can still keep my colors, draw the biggest level of the original demo, and plot a couple more enemies than I need.

I will try the quick score, thanks! What difficulties come with zoneheight 16 and text? I was thinking I would do the exact text of NES game now that I have an entire block to devote to numbers, the text I will do as sprites I think.

But the numbers are 16x16 I believe, can you even do that?

 

 

 

 

 

 

Edited by Lillapojkenpåön
  • Like 5
Link to comment
Share on other sites

Brilliant work - displaying great now and no render issues!!  I honestly believe the under the hood method is perfect for any game that renders like this + you can do animations etc. 

 

The only thing you'll find with the 16 zone height around text is you can't plot at 8 pixel increment downwards so all the text will be spaced (following the 16 zone height).  You can of course make the font up to 16 pixels high but it may just depend on how you want to present text screens. You can't currently change that on the fly as I understand.

  • Thanks 1
Link to comment
Share on other sites

Thanks man!

 

The quickscore is perfect, but how do I modify it to increment 8 positions instead of 4, for 8 wide graphics?

If you could get the quickscore example to display 2, 4, 6.. when adding 1 to the score, then it would work for me,

I don't know how to do it? 

 

And another question, if I import my letters or numbers as individual graphics instead of one big image, will the alphachars index like this one

 alphachars '0123456789abcdefghijklmnopqrstuvwxyz'

still work the same if I include the graphics in the same order and set characterset to be the zero graphic?

Edited by Lillapojkenpåön
Link to comment
Share on other sites

The pattern for a doubled quick score would be...

 scoreText5 = (scoreVar2&$0F)*2
 scoreText4 = (scoreVar2/16)*2

(Repeat that for all of the score characters. I used both "/16" and "*2" instead of just "/8" to clear out the bottom bit.)

 

alphachars and other character functions don't care if the graphics came in with one big chunk, or a bunch of discrete imports.

  • Like 2
  • Thanks 1
Link to comment
Share on other sites

47 minutes ago, RevEng said:

The pattern for a doubled quick score would be...


 scoreText5 = (scoreVar2&$0F)*2
 scoreText4 = (scoreVar2/16)*2

(Repeat that for all of the score characters. I used both "/16" and "*2" instead of just "/8" to clear out the bottom bit.)

 

alphachars and other character functions don't care if the graphics came in with one big chunk, or a bunch of discrete imports.

Awesome! Thanks!!

  • Like 2
Link to comment
Share on other sites

3 hours ago, RevEng said:

The pattern for a doubled quick score would be...


 scoreText5 = (scoreVar2&$0F)*2
 scoreText4 = (scoreVar2/16)*2

(Repeat that for all of the score characters. I used both "/16" and "*2" instead of just "/8" to clear out the bottom bit.)

 

alphachars and other character functions don't care if the graphics came in with one big chunk, or a bunch of discrete imports.

Thanks Mike - I'll update my tricks and tips for this ?

  • Like 3
Link to comment
Share on other sites

Is there any debug way to see what values are in the palettes? I've been struggeling with the fade in for a while, it's by far the hardest thing about this game so far.

I give you twenty bucks for a function RevEng ? c'mon please man ?

 

I've got a nice new topscreen, but I can't even be happy about it because of the stupid fade in!! 

 

Edited by Lillapojkenpåön
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...