English Amiga Board Printing Score with sprites (or blits)
 Register Amiga FAQ Rules & Help Members List  /  Moderators List Today's Posts Mark Forums Read

 24 April 2020, 13:17 #1 Havie Registered User   Join Date: Mar 2012 Location: UK Posts: 619 Printing Score with sprites (or blits) Hi - so I am using sprites to display the score in my Flappy Bird game (could use blits). Basically I am converting the score to a string and then slicing the string to get each digit and the converting the digit to it's value and adding this to my sprite image to get the correct number to display. Works fine. Now that I am obsessed with efficiency and speed I am pretty certain there must be a better and faster way of getting the place value digit to use to add to the sprite image? Does anyone know a clever (and quick) mathematical way of doing this? In my head you need to do this: say my number is 123 Divide the number by 100 giving 1.23 then INT the number which gives 1 so 1 is my first digit. Then subtract 100*1 from 123 giving me 23. The divide 23 by giving me 2.3 and INT (2.3) =2 so 2 is my second digit. The subtract 10*2 from 23 giving me 3 which is my final digit. This works but is it quicker? Are strings inherently slower than dividing? BUT I still wonder if this can be done more efficiently at a binary level perhaps by rotating bits? I don't know 68000 machine code and it's along time since I did anything in Z80 so this is a bit beyond me at present. Anyone clever bods out there know a better method than the two I outlined? As an aside, I always thought the INT command rounded the number but checked the manual and did a quick check and it doesn't - just chops off the decimal. There doesn't seem to be an easy way to round a decimal? Last edited by Havie; 24 April 2020 at 13:58.
 24 April 2020, 14:43 #2 Daedalus Registered User   Join Date: Jun 2009 Location: Dublin, then Glasgow Posts: 4,685 Multiplies and divides are very slow from a 68000 standpoint (though it improves as you go up the 68k range). Whether that's quicker than blitting the entire number, I don't know, but I suspect blitting 3 digits won't break the bank. Additionally, if you're working in decimals, you're involving quicks or floats which are again slower to deal with on a 68000 than bytes and words. A game I worked on a while ago (and am still working on I guess...) blits scores every frame and updates them whenever necessary, and it's running within the limits of the blitter. So I'd say keep it simple. Keep a shape's bitmap and just print the string in one go when the score changes and blit the shape whenever you need it.
 24 April 2020, 23:42 #3 Havie Registered User   Join Date: Mar 2012 Location: UK Posts: 619 So strings is the way to go - although I'm not printing the string but using it to give me the correct image to print for each digit. After the authentic Flappy Bird font! Thanks as always for your helpful advice!
 25 April 2020, 00:52 #4 jotd This cat is no more   Join Date: Dec 2004 Location: FRANCE Age: 48 Posts: 4,092 A lot of games use binary coded decimal to avoid real time divisions. ABCD/SBCD then shift 4 by 4 to get the digits. For instance if you have a score of 9546 represented it in hex: \$9546. If you add 5 points use ABCD #5, and you'll get \$9551 start with score at 0 and do your additions using ABCD. Then move score in D0 and use and #F,d0 to get the digit, display and shift using LSR.L #4,d0, repeat nb digits times.
25 April 2020, 00:55   #5
phx
Natteravn

Join Date: Nov 2009
Location: Herford / Germany
Posts: 1,649
Quote:
 Originally Posted by Havie Are strings inherently slower than dividing?
You didn't mention how you create those strings. But assuming you are generating the string from a number then Basic has already done similar division and multiplication operations.

Quote:
 BUT I still wonder if this can be done more efficiently at a binary level perhaps by rotating bits?
No. You can only do that with powers of two. On the 68000 you would use the divu instruction which gives you the integer result and the remainder of the operation at the same time. I am using BCD numbers for scores in my games, which can be converted without multiplications or divisions.

You might achieve a similar advantage when you store the single digits of your score, and write a simple addition function for it.

Quote:
 As an aside, I always thought the INT command rounded the number but checked the manual and did a quick check and it doesn't - just chops off the decimal. There doesn't seem to be an easy way to round a decimal?
INT(x+0.5)

25 April 2020, 01:21   #6
Havie
Registered User

Join Date: Mar 2012
Location: UK
Posts: 619
Quote:
 Originally Posted by phx INT(x+0.5)
Doh!

25 April 2020, 01:22   #7
Havie
Registered User

Join Date: Mar 2012
Location: UK
Posts: 619
Quote:
 Originally Posted by jotd A lot of games use binary coded decimal to avoid real time divisions. ABCD/SBCD then shift 4 by 4 to get the digits. For instance if you have a score of 9546 represented it in hex: \$9546. If you add 5 points use ABCD #5, and you'll get \$9551 start with score at 0 and do your additions using ABCD. Then move score in D0 and use and #F,d0 to get the digit, display and shift using LSR.L #4,d0, repeat nb digits times.
See- I knew that would be a clever 'shifty' way! Thanks.

 25 April 2020, 01:23 #8 Havie Registered User   Join Date: Mar 2012 Location: UK Posts: 619 But can I say - both answers blow my mind and will need some time assimilate... But thanks to both of you.
 25 April 2020, 11:12 #9 roondar Registered User   Join Date: Jul 2015 Location: The Netherlands Posts: 1,900 The big question you should really ask yourself when discussing these kind of optimisations is (well IMHO anyway): how much of an impact does changing the algorithm really have on my game. See, I love to try and find the fastest method for well anything. But I've found it's often counter productive to do so. You risk ending up spending ages optimising even the smallest aspect of your code, while not gaining much. Case in point, let's ask some questions: how much do you reckon will be saved per calculation by optimising this? how often do you actually calculate the score? Once per second? Once per frame? Ten times per frame? is your game running too slowly? Does it lose frames? The answer to these questions (and a few similar ones) should tell you how much effort to put into optimising this particular problem. I'm willing to bet that calculating the score doesn't happen more than once per frame and I'm also willing to bet it doesn't need to be done once per frame at all to still be "good enough". With that in mind, let me offer an two alternative ways of thinking about optimising the score display - neither of which remove divisions Don't optimise it at all, just leave it as is until you reach a point where the game won't run at 50Hz and you've looked at all things that do run more than once per frame already. The idea here being that you should always start optimising by looking at the most expensive/frequently execute code, not code that runs infrequently or has a small impact. Instead of calculating the entire score every frame, split the work across several frames. For instance, split it over three frames: one frame to calculate the first digit's object (and store the remainder), one frame to calculate the second digit (remainder) and one frame to calculate the third and last digit. This will be a bit more involved than the other options, but does show a key way of optimising things that don't have to run every frame to still be fine. If you really don't like the numbers updating on screen over three frames, you could either update the display during the third frame, or add a fourth frame where you deal with the display. Food for thought
 25 April 2020, 11:30 #10 jotd This cat is no more   Join Date: Dec 2004 Location: FRANCE Age: 48 Posts: 4,092 @roondar, then check Andrew Braybook games
 25 April 2020, 11:39 #11 roondar Registered User   Join Date: Jul 2015 Location: The Netherlands Posts: 1,900 Never checked his code, what did he do? Optimise everything to hell and back? (this is a serious question by the way, I'm interested to know how he did it).
25 April 2020, 12:02   #12
Havie
Registered User

Join Date: Mar 2012
Location: UK
Posts: 619
Quote:
 The big question you should really ask yourself when discussing these kind of optimisations is (well IMHO anyway): how much of an impact does changing the algorithm really have on my game.

I did this with the tile map code - moved from drawing one column a frame to breaking it down to one tile a frame and it was a massive and complicated headache that took me about 4 days to get perfect. In terms of the game - essential to keep it within 1 frame but the score code - you're right, only needs to be update every time you pass a pipe so maybe once in 60 frames (or 30 if there are more pipes on screen). SO splitting it across 3 frames would be a waste of programming time unless I need to gain speed but in this instance all I am doing in each frame is:

- 1 block for the pipe piece
- 1 sprite for the bird
- 1 line of collision check code
- updating bird movement
- updating variable that keeps track of pipe (maximum of 6 loop)
- hardware scrolling the screen

- add 1 to score and display (every 30 frames minimum)

Which without testing will easily fit one frame.

The one thing I need to test that might be a problem is moving pipes. I plan to use blits to give the illusion of movement by blitting the bottom section+gap+top section on top of the pipe - around 60 pixelsx32 and I'm not sure if lots of blits this size (maybe up to 6 ) would be doable in 1 frame. Need to experiment before I try anything more complicated which is you point!

My original thought was to use sprites but I want the background to show through the gap (obviously) so the transparency wont work in this instance as it will show the pipe underneath that should be hidden by the gap...

 25 April 2020, 12:41 #13 jotd This cat is no more   Join Date: Dec 2004 Location: FRANCE Age: 48 Posts: 4,092 Andrew (Fire & Ice, Uridium, Virocop) uses very compact assembly code, with bitfields, structures, does a lot of tricks to save a few cycles and all. for instance, when reading both joystick buttons, instead of testing bit 7 then bit 6, he does: Code: ``` move.b \$bfe001,d0 bmi .fire1notpressed btst #6,d0``` when loading in the register, it sets N if bit 7 is set (negative! and also fire not pressed). No need to test bit 7 then (but bit 6 needs testing). That's just a small example. If bits were 5 and 6 he couldn't have done that. Also, in Fire and Ice, level numbers aren't 0,1,2,3,4 ... but 0,4,8,12,16... multiplying by 4 allows to use things like Code: ``` move.w level_number(pc),d0 lea some_table(pc),a0 move.l (a0,d0.l),d1``` to get a pointer indexed on the level number without shifting D0 using LSL (or without using 68020 addressing modes (a0,d0.l*4)) saving cycles at each level is probably what makes good games fast, and bad games slow. I experienced that with Bagman remake I wrote in C++. I used the blitter and all, game has 4 planes and not a lot of objects, but the game can't run on A500 at a decent speed... He also has a middleware/mini-operating system that he uses for his games. I prefer patching games coded by non-geniuses if you ask me
25 April 2020, 13:20   #14
roondar
Registered User

Join Date: Jul 2015
Location: The Netherlands
Posts: 1,900
Quote:
 Originally Posted by jotd Andrew (Fire & Ice, Uridium, Virocop) uses very compact assembly code, with bitfields, structures, does a lot of tricks to save a few cycles and all. for instance, when reading both joystick buttons, instead of testing bit 7 then bit 6, he does: ... Also, in Fire and Ice, level numbers aren't 0,1,2,3,4 ... but 0,4,8,12,16... multiplying by 4 allows to use things like ...
Interesting stuff and exactly the kind of optimisation I was talking about. These things do save cycles. But so few of them that going out of your way to implement things this way is generally just not needed nor will it make any real difference to the end result.

Case in point: there are definitely Amiga games out there that run at 50Hz that do not use tricks like these, yet are still impressive.
Quote:
 saving cycles at each level is probably what makes good games fast, and bad games slow. I experienced that with Bagman remake I wrote in C++. I used the blitter and all, game has 4 planes and not a lot of objects, but the game can't run on A500 at a decent speed...
I'm not fully disagreeing here, do optimise as needed (or if you really like to). But there is always a caveat: saving 10-20 cycles when reading the joystick like above will only save you a positively microscopic amount of performance. IMHO you should then only go to such effort if your code needs that level of effort to perform, otherwise it's just wasted time developing that could've been spend on other tasks.

It's much better to focus optimisation efforts on things that cost a lot of cycles or happen very often. That's where the real gains are. Saving 20 cycles per loop in a loop that runs a 30 times per frame is a lot more useful than saving 100 cycles for something that runs only once per frame. Same with expensive code, optimising a 4000 cycle routine to take 10% less cycles is a lot more useful than optimising a 200 cycle routine to take 50% less cycles.

So in the case of your Bagman remake it clearly was worthwhile to optimise a lot because it didn't run well. In the case of a game that already runs at 50Hz, it's just as clearly not worthwhile to spend a lot of time optimising (unless you expect to need to do a lot more down the line or are unhappy with the number of objects/effects/etc).
Quote:
 He also has a middleware/mini-operating system that he uses for his games. I prefer patching games coded by non-geniuses if you ask me
Yeah, please don't take the above as criticism of his code, I'm merely trying to give some advice on how/when to optimise.

There is a time and place and I do advocate for writing efficient code, but focussing on eeking out that little bit of extra performance all the time is IMHO usually not worth it. Not only that, but I've found in my software developing career that it can lead to blinding you to much bigger improvements. What I mean here is optimising an existing routine to the hilt might stop you from considering thinking about an alternative approach because you're so laser-focussed on that one routine. While forgetting that a different approach might ultimately be a much better way of doing what you're trying to achieve faster.

 25 April 2020, 13:41 #15 jotd This cat is no more   Join Date: Dec 2004 Location: FRANCE Age: 48 Posts: 4,092 Agreed! I never used WinUAE hotspot feature but it is supposed to show where the code is spending a lot of time. It doesn't "clock" the code but shows the memory areas where code execution is more frequent. Of course nothing beats a real code profiler... on a modern platform.
 25 April 2020, 16:13 #16 Retro1234 Banned   Join Date: Jun 2006 Location: 5150 Posts: 4,643 You have a good point there I quite often found with Blitz and Amos that you might spend quite a bit of time trying to get code to run at a good speed on 68000 but on 68020 it would be fast maybe even too fast, a big leap in speed etc And maybe not possible in your game needs a separate score screen but use block command for the score etc and save sprites for something else. Last edited by Retro1234; 25 April 2020 at 17:45.
28 April 2020, 15:05   #17
E-Penguin
Banana

Join Date: Jul 2016
Posts: 928
Quote:
 Originally Posted by jotd A lot of games use binary coded decimal to avoid real time divisions. ABCD/SBCD then shift 4 by 4 to get the digits. For instance if you have a score of 9546 represented it in hex: \$9546. If you add 5 points use ABCD #5, and you'll get \$9551 start with score at 0 and do your additions using ABCD. Then move score in D0 and use and #F,d0 to get the digit, display and shift using LSR.L #4,d0, repeat nb digits times.
Be aware, ABCD is broken in BlitzBasic 2. It doesn't compile to the right opcode. Instead, use this macro:

https://eab.abime.net/showpost.php?p...1&postcount=27

 28 April 2020, 23:30 #18 Havie Registered User   Join Date: Mar 2012 Location: UK Posts: 619 WIP in progress now in the zone. Please feel free to let me know you thoughts... http://eab.abime.net/zone/Flappy.adf

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

 Similar Threads Thread Thread Starter Forum Replies Last Post twenty90seven support.Games 6 23 January 2015 02:19 krabob Coders. Asm / Hardware 2 15 September 2014 17:25 cybernoid project.WHDLoad 14 01 July 2008 09:32 girv Retrogaming General Discussion 33 17 August 2007 23:50 Shatterhand project.EAB 6 29 March 2003 10: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 Rules
 Forum Jump User Control Panel Private Messages Subscriptions Who's Online Search Forums Forums Home News Main     Amiga scene     Retrogaming General Discussion     Nostalgia & memories Support     New to Emulation or Amiga scene         Member Introductions     support.WinUAE     support.WinFellow     support.OtherUAE     support.FS-UAE         project.AmigaLive     support.Hardware         Hardware mods         Hardware pics     support.Games     support.Demos     support.Apps     support.Amiga Forever     support.Amix     support.Other Requests     request.UAE Wishlist     request.Old Rare Games     request.Demos     request.Apps     request.Modules     request.Music     request.Other     Looking for a game name ?     Games images which need to be WHDified abime.net - Hall Of Light     HOL news     HOL suggestions and feedback     HOL data problems     HOL contributions abime.net - Amiga Magazine Rack     AMR news     AMR suggestions and feedback     AMR data problems     AMR contributions abime.net - Home Projects     project.Amiga Lore     project.EAB     project.IRC     project.Mods Jukebox     project.Wiki abime.net - Hosted Projects     project.aGTW     project.APoV     project.ClassicWB     project.Jambo!     project.Green Amiga Alien GUIDES     project.Maptapper     project.Sprites     project.WinUAE - Kaillera Other Projects     project.Amiga Demo DVD     project.Amiga Game Factory     project.CARE     project.EAB File Server     project.CD32 Conversion     project.Game Cover Art         GCA.Feedback and Suggestions         GCA.Work in Progress         GCA.Cover Requests         GCA.Usefull Programs         GCA.Helpdesk     project.KGLoad     project.MAGE     project.Missing Full Shareware Games     project.SPS (was CAPS)     project.TOSEC (amiga only)     project.WHDLoad         project.Killergorilla's WHD packs Misc     Amiga websites reviews     MarketPlace         Swapshop     Kinky Amiga Stuff     Collections     EAB's competition Coders     Coders. General         Coders. Releases         Coders. Tutorials     Coders. Asm / Hardware     Coders. System         Coders. Scripting         Coders. Nextgen     Coders. Language         Coders. C/C++         Coders. AMOS         Coders. Blitz Basic     Coders. Contest         Coders. Entries Creation     Graphics         Graphics. Work In Progress         Graphics. Finished Work         Graphics. Tutorials     Music         Music. Work In Progress         Music. Finished Work         Music. Tutorials Off Topic     OT - General     OT - Entertainment     OT - Sports     OT - Technical     OT - Gaming

All times are GMT +2. The time now is 22:46.

 -- EAB3 skin ---- EAB2 skin ---- Mobile skin Archive - Top