English Amiga Board


Go Back   English Amiga Board > Coders > Coders. Language > Coders. Blitz Basic

 
 
Thread Tools
Old 09 January 2016, 03:22   #1
Shatterhand
Warhasneverbeensomuchfun
 
Shatterhand's Avatar
 
Join Date: Jun 2001
Location: Rio de Janeiro / Brazil
Age: 41
Posts: 3,450
How bitmaps are implented - making a scrolling game

Well, I am coding a game that uses only horizontal scroll.

The first thing I done, following Blitz 2 manual, was making a bitmap, using the Scroll function to "repeat it", then use QWrap to make the bitmap scroll infinitely. It worked great while I didn't have anything else to blit.

When I begun blitting enemies on screen, of course it didn't work, as the enemies would "teleport" when the bitmap actually wraped itself from one side to the other.

So I am scratching my head here thinking about the best way to do (and how games are usually done)

I thought about 4 ways:

a) Make a big .iff file with the whole map of the level, scroll the bitmap freely without worries

b) Make tiles, blit all I want in the bitmap, scroll the bitmap freely without worries

c) Only blit tiles when they are about to enter screen, erase them when they are out of the screen, scroll bitmap as usual even though most of it would be empty.

d) Make a bitmap just a little bit bigger than the screen, blit the tiles as shapes when they are about to enter, move each shape individually by erasing/redrawing.

I honestly don't know if there's any difference from A and B regarding either memory or CPU. And I think C will put the Blitter to work more while gaining nothing.

I really don't know how bitmap works, but I'd guess a 3000 pixels wide bitmap will always use the same amount of memory regardless if its made of a lot of different colors or is just filled with color 0 pixels. Am I wrong?

and then D would use less memory but it would be really heavy on the blitter.

So.. any clues? Any help? What should I do?

While I am at it, is there anyway to know how much memory I am using when a game is running?


Please, be kind to me, hehe. I feel this gotta be a stupid question for people who are used to code for Amiga, but I only have experience coding games for PC where I don't have to worry about any of this (And, well, ok, I coded some games on BASIC MSX, but stuff much simpler than all of this )

Thank you a lot in advance... I know I've been doing a lot of questions here, but I am really *loving* coding for Amiga, and I really want to be able to say "I've done an Amiga game in my life!" , hehe

Last edited by Shatterhand; 09 January 2016 at 05:08.
Shatterhand is offline  
Old 09 January 2016, 09:29   #2
ovale
Registered User
 
Join Date: Jun 2014
Location: milan / italy
Posts: 174
People here referenced this as the best way to implement scrolling. It is C but you can read the comments and get the idea.
http://aminet.net/package/dev/src/ScrollingTrick
ovale is online now  
Old 09 January 2016, 20:57   #3
Havie
Registered User
 
Havie's Avatar
 
Join Date: Mar 2012
Location: UK
Posts: 1,895
There is a bit of a discussion in my Flappy Bird thread on page 2 about how to do scrolling backgrounds:

http://eab.abime.net/showthread.php?t=73930&page=2

I wrote the code for this and it just about works.
Havie is offline  
Old 10 January 2016, 03:56   #4
idrougge
Registered User
 
Join Date: Sep 2007
Location: Stockholm
Posts: 4,342
Calculate enemy distance to current screen position and blit them accordingly. Remove them and repeat for next vblank.
idrougge is offline  
Old 10 January 2016, 04:24   #5
Shatterhand
Warhasneverbeensomuchfun
 
Shatterhand's Avatar
 
Join Date: Jun 2001
Location: Rio de Janeiro / Brazil
Age: 41
Posts: 3,450
Quote:
Originally Posted by idrougge View Post
Calculate enemy distance to current screen position and blit them accordingly. Remove them and repeat for next vblank.
Yeah, I begun trying to do this, when I got another more serious problem:

http://eab.abime.net/showthread.php?t=81057
Shatterhand is offline  
Old 18 January 2016, 22:33   #6
LuMan
Amigan - an' lovin' it!!
 
LuMan's Avatar
 
Join Date: Nov 2010
Location: Nottingham, UK
Age: 55
Posts: 557
Do the enemies and player Bob (I'm assuming you're using Bobs...) interact with the scrolling bitmap? If not, then use a dual-playfield to bit the player and enemies onto a blank bitmap in the foreground. You can then scroll the background however you want, while blitting the player and enemies wherever you like in the foreground.

WRT your suggestions in the first post, a and b are very similar. I've created a 5-screen wide bitmap for my GogoPogo demo level, and use the 'Show bm,x,y' (where bm is the bitmap, and x,y are the offset) approach to smoothly scroll the map. This is 32 colours and squeezes into a 1MB machine OK.

I have been toying with an approach similar to your c/d approaches. The issue comes when reaching the end of the tile-width scroll. You need to reset the position of the bitmap in the slice before redrawing the next column of tiles off-screen.. BUT you also need to copy the whole screen back to the x=0 position, otherwise all manner of odd things happen

Using the BlockScroll command is the fastest way of doing this and should fit into a vertical blank... I think.

If I get around to sorting my 'endless screen scroll' before you get a solution then I'll post it.

Good luck
LuMan is offline  
Old 19 January 2016, 02:27   #7
Shatterhand
Warhasneverbeensomuchfun
 
Shatterhand's Avatar
 
Join Date: Jun 2001
Location: Rio de Janeiro / Brazil
Age: 41
Posts: 3,450
I actually just kept the wraping of the background and I also wrap the enemies when needed. I really am using just a repating background at both background and foreground, so this works well for me
Shatterhand is offline  
Old 19 January 2016, 11:58   #8
LuMan
Amigan - an' lovin' it!!
 
LuMan's Avatar
 
Join Date: Nov 2010
Location: Nottingham, UK
Age: 55
Posts: 557
OK, I've thrown together a very quick demo, which will eternally scroll horizontally.

Basically, it stamps blocks in random positions on the screen and starts scrolling. Once it hits 16 pixels (block width) it copies the current view (16 pixels into the bitmap) back to the start and adds another vertical strip of blocks. Then loops.

The blocks in the off-screen strip are added randomly, but could easily be gathered from a List or Array to make a mapped scrolling image.

I've done this on my A1200, so will upload to The Zone shortly.

About the code:
It's not optimised, but it does the trick.
It uses a second bitmap only for the BlockScroll and new column routine. If you BlockScroll onto the active bitmap, then you'll get flickering, as you'll have 1 frame (ish) with both old and new images being shown.
I have used 2 VWaits for normal scrolling, and only 1 VWait for the bit where a new column is added. This evens up the slight wait in the computer drawing the off-screen column and makes things smooth. You could look at the timing with Vpos and try to squash the BlockScroll into the vertical flyback and do away with the extra bitmap
By default the map scrolls at 1 pixel per 2 frames, which looks slow, but smooth. Using the Joystick you can speed up to 5 pixels by pressing Right, or slow down to 0 (stop) by pressing left.
This works fine on my 040/25 A1200, but should still be OK on most Amigas, as we are doing a fair bit of waiting around for the VWaits.
The joystick fire button stops the demo.

EDIT: File uploaded to The Zone

Last edited by LuMan; 19 January 2016 at 12:06. Reason: Uploaded file
LuMan is offline  
Old 19 January 2016, 13:52   #9
Master484
Registered User
 
Master484's Avatar
 
Join Date: Nov 2015
Location: Vaasa, Finland
Posts: 525
One scrolling method theory that I have been thinking myself, is this:

First make one bitmap that is 3 screens wide, and fill the screens with block tile graphics. Each screen can be different, so you'll have screens that look like "A, B, C".

And when Player is travelling through these screens, in the background gradually build a second bitmap, which will look like: "C, D, E". So the last screen of the first bitmap "C" looks exactly the same as the first screen of the second bitmap. When Player reaches screen C of the first bitmap, switch screen position and all action to the C screen of the second bitmap and delete the first bitmap from memory. And now you can start building a third bitmap that'll be: "E, F, G". so again the last and the first screen, in the case "E", are the same.

So it'll go like: ABC-CDE-EFG and so on.

The benefit of this method would be that there is no need to stop and copy/update screen information at any point.

And when building the screens in the background, even as slow rate as 2 new 16*16 blocks per frame could be enough. Each screen needs 320 16*16 blocks, and at 2 blocks per frame filling rate you would get 100 blocks per second, so it would take approximately 3 seconds to fill one screen, and 9 or 10 seconds to fill all three screens...this might be enough for a "relaxed speed" scroller. But of course I think a making a full column of sixteen 16*16 blocks per frame would still possible; with this speed you would get 2 new screens in one second. Or at 8 new blocks per second you would get 1 new screen per second.

And also, instead of having two 3 screen wide bitmaps, maybe just one 6 screens wide bitmap would be enough, and the "switch between the bitmaps" would be made by simply scroll-teleporting the view to the second 3 screen part. And when Player is progressing through the second part, in the background gradually overwrite all stuff in the first part, and then switch back to it when player reaches the end of the second part. And then repeat this process.

---

But I haven't tested this yet, so I can't be sure how it'll work. And this method would only be good for a one-way horizontal scroller.

But I believe that an advanced version of it could be used for an 8-way scrolling platformer too, such as Megaman X, but the bitmaps would need to be slightly larger, and the switching of bitmaps would be done in a "rest room area", which would be a one-screen room that the Player must go through. And luckily in a game like Megaman X this is easy to do: Just add mid-bosses and "stay here for a while and defeat those enemies before you can progress"-type of rooms to spots where the bitmap switch takes place. And in fact I think this is what the SNES original is doing all the time, especially in Megaman X2 and X3.
Master484 is offline  
Old 19 January 2016, 15:30   #10
LuMan
Amigan - an' lovin' it!!
 
LuMan's Avatar
 
Join Date: Nov 2010
Location: Nottingham, UK
Age: 55
Posts: 557
That's a pretty good approach, Master484. If it was a platform game, where you would be milling about in the middle of the screen for a bit, then it would work OK (in theory, at least).

For an 8-way scroller you would need something like a 3x3 screen approach and start building the centre screen when you are halfway into any of the 'outer' screens.

WRT the solution I posted earlier, this also be modified to be 8-way by creating both vertical and horizontal strips of blocks, depending on scroll-direction. In fact, it could incorporate your suggestion of adding a new block or two every frame until the next strip is finished. If the blocks were 32x32pixels, instead of 16x16pixels, we'd have twice as long to blit half as many tiles... hmmm... but I think it would still be slower doing the BlockScroll than to flip to the other bitmap.

Of course, the quickest way is to create super bitmaps and be very careful with colours and tiles, so that you can build a bitmap in the smallest possible memory. But this sort of defeats the feeling of this thread
LuMan is offline  
Old 19 January 2016, 16:51   #11
idrougge
Registered User
 
Join Date: Sep 2007
Location: Stockholm
Posts: 4,342
@Master,
I think that's the same concept I did in AMOS here. http://eab.abime.net/showthread.php?t=80646
idrougge is offline  
Old 19 January 2016, 17:13   #12
LuMan
Amigan - an' lovin' it!!
 
LuMan's Avatar
 
Join Date: Nov 2010
Location: Nottingham, UK
Age: 55
Posts: 557
How about this...

You have a 3-screen-wide bitmap, built from 32px tiles, the order of which is held in a List (or Array).

The screens are A-B-C, and only screens A & B are drawn before the scroll starts.
Once you get to the 32px point of your scroll, you start blitting (or Blocking - it's quicker) the top block of the first vertical strip of C, while also Blocking the same block to the first vertical strip of A. Both of these strips are off-screen at this point.
Every frame you add the next pair of blocks until the strips are complete.
If you scroll at 1 or 2 pixels per frame, you will have 32 or 16 frames to Blit/Block 8 pairs of blocks.
Once you hit the end of Screen B, and enter Screen C in total, you will have an identical copy in Screen A and can reset your Show x,y offset back to 0 again. Sorted.

Effectively, you could scroll at 4px/frame and just squeeze all 8 pairs in before they need to be shown. An A1200 could probably do more.

I've not got time to try this tonight, but I may see if I can get a rough demo working tomorrow, as I have another game idea that I'm working on that may be able to use it....
LuMan is offline  
Old 19 January 2016, 19:04   #13
Retro1234
Phone Homer
 
Retro1234's Avatar
 
Join Date: Jun 2006
Location: 5150
Posts: 5,790
http://eab.abime.net/showthread.php?p=757200#post757200

or what idrougge put this is how you do Hardware scrolling on Amiga, it doesnt matter the language

this works in all directions if you scroll Down+Right you basicly end up with four screens the same when you reach the bottom.

Now days some people have thought about using one large screen and large image id be interests to know how this works out.

Last edited by Retro1234; 19 January 2016 at 22:26.
Retro1234 is offline  
Old 19 January 2016, 20:23   #14
Master484
Registered User
 
Master484's Avatar
 
Join Date: Nov 2015
Location: Vaasa, Finland
Posts: 525
@idrougge
Yes, I took a quick look at the code and your scroll method seems quite similar.

@LuMan
Your version of the A-B-C scroll sounds indeed better, only three bitmaps needed to achieve the same thing that needed 6 bitmaps in my example.

This scroll method would work well in shoot'em ups at least where the screen always scrolls forwards and never backwards; all bitmap area which has been scrolled is instantly available for re-drawing.

Quote:
For an 8-way scroller you would need something like a 3x3 screen approach and start building the centre screen when you are halfway into any of the 'outer' screens.
Yes that's what I've been thinking too if the "add new tiles as scroll progresses" method would be used in a 8-way scrolling platformer. But this creates some problems like when player moves into the crossroads area where the corners of four screens connect, and three of those screens would be the "outer screens" of the 3x3 area.

For example if player started on the middle screen and moved diagonally up-right, then soon the player would be in the junction area of four screens at once: the middle screen, top screen, top right screen and right screen. And because we don't know what direction the player will go next, we would need to start drawing at least 4 new screens. But if the drawing routine was smart and efficient enough, then maybe this method could work. Although it would still mean continuous tile drawing, and we would need at least twice as much new tiles per frame than in a single-direction scroller. And also all screens that we have already drawn would need to be drawn again if the player decides to return back.

So I think that for a 8-way platformer it would be much easier to simply build all screens before the level even starts, like have maybe 9 screens worth of play area ready, and when player has progressed through these, he will then enter a "delay room" or "delay screen", where scroll stops and player either fights enemies or solves a puzzle, or does something else which is guaranteed to take a certain amount of time (like 10 seconds), and during this time the map drawing routine will build the next set of 9 screens.

I think this would be more clear and easier to make, and also save more blitting power for the action.

But I wonder how many screens the standard 1MB A500 can hold in memory at once? Assuming that the screens were built from 16*16 blocks of 16 colors, and other graphics and sound might take about half of that 1MB...so we would have maybe 500kt of RAM left for those screens?

I already counted that 320*256 = 81920. So if those are bytes, then a 320*256 bitmap would take about 82kb of memory. So 6 such screens would be enough to fill that 500kt. But is this correct or is the bitmap memory usage calculated in some other way?
Master484 is offline  
Old 19 January 2016, 22:32   #15
ReadOnlyCat
Code Kitten
 
Join Date: Aug 2015
Location: Montreal/Canadia
Age: 52
Posts: 1,178
Oki. Don't take it badly but all these suggestions are the wrong way to do scrolling on the Amiga. They all consume way more blitter time than is necessary.

I do not really have time now to go into details but will do so tonight but in short what you want to do is leverage hardware scrolling and the Copper in order to blit only the soon to be visible tiles and nothing else.

Your suggestions and ideas are not bad per se, these are the ones that everyone starts with at the beginning but they are not efficient.

The proper way to implement scrolling varies depending on the type of scrolling needed and in the case of horizontal scrolling there is a super simple way to do it: search for "Akira Codetapper ReadOnlyCat NorthWay scrolling" and you should find the thread where Codetapper describes the best method.

I'll give more details soon if needed.
Cheers!
ReadOnlyCat is offline  
Old 19 January 2016, 22:37   #16
Retro1234
Phone Homer
 
Retro1234's Avatar
 
Join Date: Jun 2006
Location: 5150
Posts: 5,790
I think me and idrougge have put the correct method I even described the result of a sideways scroll down and right this full 8 way hardware scrolling.

I mean come on scroll 1 pixel paste 1 tile.
Retro1234 is offline  
Old 20 January 2016, 00:38   #17
ReadOnlyCat
Code Kitten
 
Join Date: Aug 2015
Location: Montreal/Canadia
Age: 52
Posts: 1,178
Quote:
Originally Posted by Boo Boo View Post
I think me and idrougge have put the correct method I even described the result of a sideways scroll down and right this full 8 way hardware scrolling.

I mean come on scroll 1 pixel paste 1 tile.
This solution wastes enormous amount of memory.
Just do the search I recommended above and you will have a full explanation.

To scroll 16000 pixels horizontally, one only needs 1000 additional bytes to the full bitmap size. Your solution would require 50 complete additional screen sized bitmaps to achieve it.
ReadOnlyCat is offline  
Old 20 January 2016, 00:45   #18
Retro1234
Phone Homer
 
Retro1234's Avatar
 
Join Date: Jun 2006
Location: 5150
Posts: 5,790
please explain 50 completea dditional screens? 672*544 I can basicly scroll unlimited any direction.

Last edited by Retro1234; 20 January 2016 at 00:51.
Retro1234 is offline  
Old 20 January 2016, 06:10   #19
ReadOnlyCat
Code Kitten
 
Join Date: Aug 2015
Location: Montreal/Canadia
Age: 52
Posts: 1,178
Quote:
Originally Posted by Boo Boo View Post
please explain 50 completea dditional screens? 672*544 I can basicly scroll unlimited any direction.
You did not do the search I recommended did you?

Ok, now that I have a real keyboard I can go more into details.

First, for reference, let me insist that I learned the technique via Codetapper who explained it in the Horizontal vs vertical scrolling thread created by Akira. I personally would have gone with a Copper-split technique if I had not learned of this alternative.

The idea is to allocate a bitmap of the usual size:
- one screen width + one or two rows of tiles (depending on the desired scroll speed)
- one screen height (if no vertical scrolling is needed)
then add a tiny bit of memory at the end of the bitmap depending on the total length of the scroll.

Once that is done, the bitplanes registers are set to point at the top of the bitmap like for any regular screen. Then, when the screen scrolls, one simply increments the hardware registers (or "screen offset" I guess in Blitz) to make the image scroll to the left while pre-drawing the tiles on the not-yet-visible part of the bitmap (on the right of the bitmap/screen).

And... that's it. No kidding!

The trick is that, as the screen scrolls to the right (which means the pixels visually scroll to the left), the part of the bitmap which used to be the left part of the screen starts to arrive on the right side of the screen. Since the display fetches data from memory in increasing order, the display essentially wraps around the screen like a corkscrew.

To visualize what is happening, do the following experiment:
- load an image
- scroll indefinitely to the left, that is, keep increasing the horizontal offset of the screen
The pixels on the left side start re-appearing on the right, then they reach the left of the screen again and the image has essentially gone one line "up" in addition to one row "left".

When tiles are drawn on the right side of the bitmap, this wrapping is hidden since only the pixels of the newly written tiles appear from the right.

The end-result is that for every pixel scrolled to the left, you only need one pixel added at the end of the bitmap in order to "stay in the bitmap". If you need to scroll 16000 pixels (= 50 screens), just add 16000 worth of pixels to the size of the bitmap when allocating it.

That is only 16000/8*5=10KiB in 32 colours, much less than a full size screen.
In comparison, the added memory to reach 676*500 is three times the amount needed for a single screen and represents 336*272*3*5/8=170KiB! This is about one fourth of 512KB just for the screen.

The corkscrew technique has thus many advantages:
  • It consumes very little additional memory compared to a single screen.
  • It requires the minimum possible amount of blits (i.e., just blit new tiles).
  • It requires the minimum possible amount of CPU (only the biplanes and delay registers need to be updated = screen offset in Blitz).
Hopefully, this little drawing should help visualize it:
Code:
Large bitmap technique
+--------------------+
                       +-------------------------------------+
    + Screen offset    |                                     |
    |       = (4,1)    |                                     |
    ^                  V                                     |
+---------------------------------------------+              |
|   +-----------------+N               BITMAP |              |
|   |    SCREEN       |N                      |              |
|   |                 |N  <----+ column of    |              |
|   |                 |N         new tiles    |              |
|   |                 |N                      |              |
|ABC|EFGHIJLKMNOPQRSTU|N YZ01234567890ABCDEFGH|              |
|   |                 |N                      |              |
|   |                 |N                      |              |
|   +-----------------+N                      |              |
+---------------------------------------------+              |
                                                             |
                    +--------------------------------------------+
                    |                                        |   |
                    |   + Screen offset = (26,1)             |   |
                    V   V                                    |   |
+---------------------------------------------+              |   |
+------------------+N   +-----------------+N  |              |   |
|                  |2   |    SCREEN       |N  |              |   |
|                  |N   |                 |N  |              |   |
|                  |2   |                 |N  |              |   |
|                  |N   |                 |N  |              |   |
|234567890ABCDEFGHI|2 VW|YZ01234567890ABCD|NGH|              |   |
|                  |N   |                 |N  |              |   |
|                  |2   |                 |N  |              |   |
+------------------+N   +-----------------+N  |              |   |
+---------------------------------------------+              |   |
             ^                                               |   |
             |                                               |   |
Screen will be here soon.                                    |   |
So this must be drawn while scrolling.                       |   |
                                                             |   |
  Problems:                                                  |   |
  - must blit TWO columns of new tiles (FOUR if hor+ver)     /   |
    - one to the right of the screen because of the scrolling    |
    - one to the left of the screen to have a full screen ready -+
      when the bitmap is reset to (1,1)
  - needs a bitmap TWO times larger than the screen (scroll horizontal)
    or FOUR times larger (horizontal + vertical

Corkscrew technique
+-----------------+

+ Screen offset = (0,0)    Screen offset = (1,0)
|                         |
v                         v
+------------------+N    +-------------------+
|    SCREEN        |N    N|    SCREEN        |
|                  |N    N|                  |
|                  |N    N|                  |
|ABCDEFGHIJKLMNOPQR|N    N|BCDEFGHIJKLMNOPQRS|
|                  |N    N|                  |
|                  |N    N|                  |
|                  |N    N|                  |
+------------------+N    N+------------------+
|    BITMAP         |    N    BITMAP         |
+-------------------+    +-------------------+

  Screen offset = (2,0)    Screen offset = (3,0)
    |                         |
    v                         v
+-------------------+    +-------------------+
|   |    SCREEN     |    |    |     SCREEN   |
+-+N|               |    +--+N|              |
| |N|               |    |  |N|              |
| |N|CDEFGHIJKNOPQRS|    |  |N|DEFGHIJKNOPQRS|
|T|N|               |    |TU|N|              |
| |N|               |    |  |N|              |
| |N|               |    |  |N|              |
| |N----------------+    |  |N---------------+
+-+N BITMAP         |    +--+N       BITMAP  |
+-------------------+    +-------------------+

More efficient:
- only one column of tiles to draw
- just keep increasing the screen offset horizontally
- very little memory usage:
  for one pixel scrolled, just allocate one more pixel of bitmap
Hope this helps!
ReadOnlyCat is offline  
Old 20 January 2016, 07:07   #20
Retro1234
Phone Homer
 
Retro1234's Avatar
 
Join Date: Jun 2006
Location: 5150
Posts: 5,790
I think its better to have a larger screen to allow baddies on and off left and right - ok you dont need the full 672 and your method wont work on the vertical.

but dont over complitate it You scroll right you paste a Tile to the right -you scroll down you paste a tile at the bottom.
Retro1234 is offline  
 


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools

Similar Threads
Thread Thread Starter Forum Replies Last Post
Making a Cracktro-Like Text Scrolling Effect mattbarton.exe Amiga scene 12 31 May 2022 21:12
side scrolling, ball kicker platform game AnonA Looking for a game name ? 15 17 August 2010 21:15
[Found: Australo Piticus Mechanicus] Side scrolling barb game, old? Wasagi Looking for a game name ? 5 03 July 2010 00:08
Vertical scrolling motorcycle game.. Anyone? Thrash75 Looking for a game name ? 11 18 May 2005 19:44
Side scrolling terrorist game. Jay Fat Looking for a game name ? 8 25 November 2004 00:14

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +2. The time now is 21:28.

Top

Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.
Page generated in 0.10315 seconds with 13 queries