English Amiga Board


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

 
 
Thread Tools
Old 09 April 2020, 21:01   #1
Havie
Registered User
 
Havie's Avatar
 
Join Date: Mar 2012
Location: UK
Posts: 1,893
Fastest Technique for clipping a screen

Hi

I was revisiting my Flappy Bird game as I was always unhappy with how it runs and it transpires that I use too many Block commands to clip the edges of the screen (the screen is only 156 pixels wide and centred on a low res screen. Pipes slide in from the right 24 pixels right of this and I then use block to put a vertical black bar on top of the pipe to clip it. Same happens on the left so the pipes slide smoothly off screen.

If I remove the two vertical black blocks then the game runs significantly faster and thus I can move the pipes 1 pixel per loop instead of 3 which makes them smoother. Also, as the game is running faster, the bird movement is smoother and feels more like Flappy Bird.

An alternative method of clip I have tried is using a third bitmap (two already used for double buffering). I draw everything to the third bitmap and the grab the section in the middle and copy that to my current double buffer screen. I have used Getasprite and block first and then tried Scroll to copy from bitmap 3 to the current one. This seems a bit faster but I'm not sure if there is a better way?

I did consider using a dual playfield and using the foreground to clip the background but then this reduces the colours to 8 so graphics look a bit rubbish.

My final idea (yet to try) is to have the pipe on screen 3 and then copy it in 1 pixel chunks to the double buffered screen i.e. 1 line of vertical pixels, then 2 lines of vertical pixels, 3 lines etc so I can create the illusion of the pipe sliding in (would need to repeat this on the other side).

Can anyone think of a quicker way to copy part of a screen to another or a more intelligent way of clipping and making a window on a bitmap screen?

P.S. I tried Bitmapwindow first but got no where!
Havie is offline  
Old 09 April 2020, 21:49   #2
Daedalus
Registered User
 
Daedalus's Avatar
 
Join Date: Jun 2009
Location: Dublin, then Glasgow
Posts: 6,334
So how is the game constructed? Are you scrolling the bitmap or leaving it static? Are you using the Display Library? Perhaps a different approach might be to make the screen itself narrower using the DisplayAdjust command, so no need for the black boxes. Or even simpler, use some static sprites filled with black to mask off the unwanted areas of the screen?
Daedalus is offline  
Old 09 April 2020, 23:19   #3
Havie
Registered User
 
Havie's Avatar
 
Join Date: Mar 2012
Location: UK
Posts: 1,893
Static screen with shapes blitted on to it.

I had thought of narrowing the screen with DisplayAdjust but not sure how to do this or whether it would work? Would it be possible to narrow the screen whilst keeping an unseen section to avoid having to use ClipBit?

BUT

I like the idea of replacing the black bars with sprites! This sounds like a goer to me... 4 full screen height sprites should be enough and in theory they wouldn't impact on the speed of the game.

Will report back!
Havie is offline  
Old 10 April 2020, 00:03   #4
Havie
Registered User
 
Havie's Avatar
 
Join Date: Mar 2012
Location: UK
Posts: 1,893
Had a quick test with sprites and it works really well!

Of course, how you code depends on whether using AGA or non-AGA. I am targeting ECS/OCS minimum whereas if I was targeting AGA I could make the pipes out of sprites instead or shapes (I could attempt to multiplex the sprites I suppose).

Anyway, I will use sprites to clip and fiddle a little more and hopefully sometime over the weekend I will release a new, spangly version of my Flappy Birds game which is faster and smoother...

Thanks for your help!
Havie is offline  
Old 10 April 2020, 00:19   #5
Daedalus
Registered User
 
Daedalus's Avatar
 
Join Date: Jun 2009
Location: Dublin, then Glasgow
Posts: 6,334
Nice Sprites are effectively free once they're set up, so shouldn't impact the game speed at all. They're often used in games for score bars and overlays so work well in that capacity. As for narrowing the screen, it's a bit of a black art but can be done with a bit of fiddling. If you use a bitmap that's wider than the screen, you can position it with, say, 50 pixels either side of the viewable area and simply blit where you like while only able to see the middle portion of the image. But if sprites are working for you, that's the way to go.
Daedalus is offline  
Old 10 April 2020, 15:12   #6
Master484
Registered User
 
Master484's Avatar
 
Join Date: Nov 2015
Location: Vaasa, Finland
Posts: 525
Quote:
I had thought of narrowing the screen with DisplayAdjust but not sure how to do this or whether it would work? Would it be possible to narrow the screen whilst keeping an unseen section to avoid having to use ClipBit?
DisplayAdjust is a complicated command, but a simple "screen cut" like that is easy to do, and you only need to care about the two last parametres of the command:

DisplayAdjust CoplistID,0,0,0, LeftSideCutAmount, RightSideCutAmount

The "LeftSideCutAmount" is a positive value, but "RightSideCutAmount" needs to be a negative value.

So for example, if you have a 320 pixel wide screen, and want to "hide" 32 pixels from both sides, then the command to do that is:

DisplayAdjust CoplistID,0,0,0,32,-32

And to narrow the visible area to 156 pixels use "82" and "-82".

After this the bitmap itself will still 320 pixels wide, but only pixels from 82 to 238 are visible.

---

When using DisplayAdjust, bitmap size of 320 pixels is the easiest size, because it automatically centers perfectly into the screen. But if you want to center/cut bitmaps that are smaller than 320 pixels, then the DisplayAdjust command will need those other parametres too.

For example to center a 288 pixel wide bitmap/screen in one of my own projects I use:

DisplayAdjust CoplistID,-2,8,0,16,-16

---

Also, if your game has a static background that doesn't scroll, and the ground and pipes move over that, then you can boost speed by using the "Qblit + Unqueue source" method.

So in addition to your double buffer bitmaps, make a third bitmap which contains a "clean copy" of the background; so it has the background only without any blits. To this clean backround you never draw anything.

Then draw the pipes and the ground normally to your double buffer bitmaps using Qblit. And then to the end of the Unqueue command you put the ID number of that third bitmap, and it'll clean the Qblits, restoring graphics from that clean background.

So all you need is third bitmap with a clean background, and then just use Qblit to draw stuff, and do unqueue like this: Unqueue QueueID, RestoreBitmapID
Master484 is offline  
Old 10 April 2020, 18:04   #7
Daedalus
Registered User
 
Daedalus's Avatar
 
Join Date: Jun 2009
Location: Dublin, then Glasgow
Posts: 6,334
@Master484

Thanks for that Whenever I use DisplayAdjust, I need to sit down with a pen and paper and slowly work through it with the hardware reference manual. So I try to avoid it
Daedalus is offline  
Old 10 April 2020, 19:50   #8
Havie
Registered User
 
Havie's Avatar
 
Join Date: Mar 2012
Location: UK
Posts: 1,893
So which is quicker - using 4 screen height sprites or DisplayAdjust?

Is there anyway of finding out the FPS (I'm using WinUae for programming and testing).
Havie is offline  
Old 10 April 2020, 20:24   #9
Daedalus
Registered User
 
Daedalus's Avatar
 
Join Date: Jun 2009
Location: Dublin, then Glasgow
Posts: 6,334
Really, once you reach 50 FPS, you won't get any more out of it, since you want to synchronise with the display to avoid tearing or glitches. What you can do is set the background colour to a different colour at different points in your loop. You can then judge how much of the frame is taken up by a certain part of the code by how much of the background is filled with that colour. Don't forget to set WinUAE to "cycle exact" speed or everything will take basically no time It might look something like this:

Code:
; Loop start
Poke.w $dff180, $f00 ; Red

; Draw your pipes

Poke.w $dff180, $0f0 ; Green

; Draw your bird

Poke.w $dff180, $00f ; Blue

; Do your movement

Poke.w $dff180, $ff0 ; Yellow

; Do your collision detection

Poke.w $dff180, $0ff ; Cyan

; End of loop

Poke.w $dff180, $f0f ; Magenta
So if most of the screen is yellow for example, you know that collision detection is taking up a lot of time. I suspect both methods would be very efficient, essentially free, because once they're set up, nothing really needs to be done in your main loop to maintain them. The magenta will show you how much time is free at the end of each frame, so if that is about the same amount with both techniques, then you know there's no major difference other than your preference.

Last edited by Daedalus; 10 April 2020 at 20:36.
Daedalus is offline  
Old 10 April 2020, 22:46   #10
Master484
Registered User
 
Master484's Avatar
 
Join Date: Nov 2015
Location: Vaasa, Finland
Posts: 525
Quote:
So which is quicker - using 4 screen height sprites or DisplayAdjust?
DisplayAdjust is a little bit quicker, for two reasons. Firstly, sprites are super fast, but not totally free, especially if they're as tall as the whole screen. And secondly, if you use DisplayAdjust, then you can use those sprites for something else, like the bird character, which would save one Blit.

But I agree that the sprites are a lot easier solution to the problem that you have.

Quote:
Is there anyway of finding out the FPS
As Daedalus mentioned, changing the background color is an easy way to evaluate program speed. But if your main loop takes more than one frame to execute, then the color changes won't produce accurate results.

This is why I usually use a more complex method to measure program performance, and it goes like this:

First make a small VBLANK interrupt routine, that looks like this:

SetInt 5
framespassed + 1
End SetInt


Put that somewhere before the main loop starts.

And then reset the "framespassed" variable to 0 just before VWait happens, like this:

framespassed = 0
VWAIT


And then, you can combine this with the "VPos" command, and print both values to screen:

VERTPOS = VPos
Print "V", VERTPOS, " F", framespassed," "
framespassed = 0
VWAIT


The "framespassed" variable tells how many frames it takes to complete one program loop. If it's 1, then your program runs at 50 FPS. If it's 2, then it runs at 25 FPS. And if it's 3, then it runs at 17 FPS, and so on.

And the "VPos" command tells the vertical line where the display beam is currently located. So this way you'll know both the FPS, and the status of the current frame.

However, notice that the print command itself is slow, and this will have an effect to program performance (each letter printed is basically one Blit). This is why I always make a key that can turn the text priting ON/OFF. And if possible I also print to a separate screen area, and not the main game screen, and do the print only once per second or something.

Also, if you want to stop the VBLANK interrupt, then "ClrInt 5" will do this.

---

So this is quite complex, but I think it's the only way to know how many frames your main loop takes. And also the VPos value is super helpful; it shows real numbers on screen instead of colors, and you can see how even small code changes will change the numbers, which really help when you're optimizing the code.

Last edited by Master484; 10 April 2020 at 23:19. Reason: fixed a small mistake
Master484 is offline  
Old 11 April 2020, 10:19   #11
E-Penguin
Banana
 
E-Penguin's Avatar
 
Join Date: Jul 2016
Location: Darmstadt
Posts: 1,213
It's a bit of a cheat perhaps but I usually make my bitmap wider than the screen, by 2 x widest blob, and centre the screen so that these extra pixels aren't shown. I can then start blitz outside the visible area and move them in as needed. Then I don't ever need to worry about clipping as every blit fits on the bitmap and the hardware takes care of the rest.
E-Penguin is offline  
Old 11 April 2020, 12:33   #12
roondar
Registered User
 
Join Date: Jul 2015
Location: The Netherlands
Posts: 3,410
About making the screensize smaller using the display library: apart from Master484's notes on that, there is another reason that doing this is faster than using sprites. On the Amiga, the display "steals" cycles from the Blitter (and the CPU if you're using more than 16 colours or using Dual Playfield mode). A smaller display means less of this happens.

A normal screen (320x256x16 colours) will lose you on the order of 30% of the Blitter's maximum performance. This scales linearly (though it rounds on 16 pixel intervals). So, dropping the width to 156 pixels will therefore lose you only ~15% of the Blitter's maximum performance rather than the 30%. This is a fairly big improvement and certainly cheaper than using sprites.
roondar is offline  
Old 11 April 2020, 12:43   #13
Havie
Registered User
 
Havie's Avatar
 
Join Date: Mar 2012
Location: UK
Posts: 1,893
Quote:
Originally Posted by E-Penguin View Post
It's a bit of a cheat perhaps but I usually make my bitmap wider than the screen, by 2 x widest blob, and centre the screen so that these extra pixels aren't shown. I can then start blitz outside the visible area and move them in as needed. Then I don't ever need to worry about clipping as every blit fits on the bitmap and the hardware takes care of the rest.
That wont work as I’m using a screen only 156 pixels wide (perhaps I need to make it 160).
Havie is offline  
Old 11 April 2020, 12:43   #14
Havie
Registered User
 
Havie's Avatar
 
Join Date: Mar 2012
Location: UK
Posts: 1,893
Quote:
Originally Posted by roondar View Post
About making the screensize smaller using the display library: apart from Master484's notes on that, there is another reason that doing this is faster than using sprites. On the Amiga, the display "steals" cycles from the Blitter (and the CPU if you're using more than 16 colours or using Dual Playfield mode). A smaller display means less of this happens.

A normal screen (320x256x16 colours) will lose you on the order of 30% of the Blitter's maximum performance. This scales linearly (though it rounds on 16 pixel intervals). So, dropping the width to 156 pixels will therefore lose you only ~15% of the Blitter's maximum performance rather than the 30%. This is a fairly big improvement and certainly cheaper than using sprites.
Ok - this is my next iteration especially if it gets me some glitter time back...
Havie is offline  
Old 11 April 2020, 13:32   #15
Havie
Registered User
 
Havie's Avatar
 
Join Date: Mar 2012
Location: UK
Posts: 1,893
Easy change - comment out the sprites and add the DisplayAdjust command - works really well.

Also, adding the pokes, I can see (not surprisingly) that 6 big Blits (Clipbits at that) take up most of the time (and this is fastest speed WinUae). When I try on an A500+ (WinUae) it's pretty slow...

Now that they sprites are free, it would make sense to use sprites instead of Blits as this are quicker and don't need clipping.
Havie is offline  
Old 11 April 2020, 13:43   #16
roondar
Registered User
 
Join Date: Jul 2015
Location: The Netherlands
Posts: 3,410
Yup, always use the HW sprites to the max if you can. They're so efficient
roondar is offline  
Old 11 April 2020, 14:37   #17
E-Penguin
Banana
 
E-Penguin's Avatar
 
Join Date: Jul 2016
Location: Darmstadt
Posts: 1,213
Quote:
Originally Posted by Havie View Post
That wont work as I’m using a screen only 156 pixels wide (perhaps I need to make it 160).
Yes it will - define your bitmap to be 156+24+24, and display it at offset 24. Then you've got 24 pixels each side into which you can blit your pipes which are off-screen--then move them one pixel at a time into the visible bit
E-Penguin is offline  
Old 11 April 2020, 18:14   #18
Daedalus
Registered User
 
Daedalus's Avatar
 
Join Date: Jun 2009
Location: Dublin, then Glasgow
Posts: 6,334
I definitely reckon you should increase your bitmap size and just use standard blits that overflow safely into areas of the bitmap that are unseen, rather than clipped blits. I haven't measured it myself, but I would expect the clipping action could be slow, so that alone should give you a speed boost at the cost of a little bit of chip RAM. If you can implement them as sprites though, that's definitely the way to go.
Daedalus is offline  
Old 11 April 2020, 19:06   #19
Havie
Registered User
 
Havie's Avatar
 
Join Date: Mar 2012
Location: UK
Posts: 1,893
Well...with all the discussion I have had a rethink and what was a slight upgrade is now in danger of being a full rewrite!

The original game worked like this to build up the screen:
1. Block - background
2. Blit top pipe and leave gap and blit the bottom pipe. Pipes 190 pixels high so need Clipbliting.
3. Block two black bars either side of screen to make window and hide pipes blitted to slide smoothly on to screen.
4. Blit scrolling bar at bottom of screen (wider than window so it can move smoothly and then reset.
5. Blit yellow rectangle at bottom of screen to hide bars that are off screen.
6. Print score and high score

Total of 1 block and 10 blits (of big objects) and 2 prints.

Slow but seemed to work (not terribly smooth as bars moved 3 pixels for speed)

Now:
1. Set up screen with DisplayAdjust (including yellow bar at the bottom) and print high score in bottom of screen.
2. Blit pipe (height of screen with both top and bottom) with no gap (no need for Clipblit and no need to re-blit yellow bar)
3. Use a sprite as the gap.
4. Blit scrolling bar.
5. Print score.

Use the three screen method and qbits as suggested above for maximum blitting speed.

Total of 4 blits and 3 sprites and 1 print plus faster blitting.

And breath...
Havie is offline  
Old 11 April 2020, 19:12   #20
Havie
Registered User
 
Havie's Avatar
 
Join Date: Mar 2012
Location: UK
Posts: 1,893
I also realised that I am checking the collision with all pipes each loop but only one needs to be checked.

Just need to workout collision with the one pipe - probably stick to Shapeshit.
Havie 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
Ripping Sprites - Technique... method project.Sprites 43 12 October 2021 16:17
Amazing New Retrobrighting Technique Hewitson Retrogaming General Discussion 12 12 June 2019 09:27
Disable bob clipping at screen edges adrazar Coders. AMOS 15 03 July 2017 13:57
Fastest way to blit things on screen Shatterhand Coders. Blitz Basic 13 03 February 2016 10:12
Screen right edge clipping issue mark_k support.WinUAE 0 05 January 2014 19:28

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 17:20.

Top

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