24 April 2020, 13:17 | #1 |
Registered User
Join Date: Mar 2012
Location: UK
Posts: 1,893
|
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 |
Registered User
Join Date: Jun 2009
Location: Dublin, then Glasgow
Posts: 6,334
|
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 |
Registered User
Join Date: Mar 2012
Location: UK
Posts: 1,893
|
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 |
This cat is no more
Join Date: Dec 2004
Location: FRANCE
Age: 52
Posts: 8,161
|
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,<value> 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 | ||
Natteravn
Join Date: Nov 2009
Location: Herford / Germany
Posts: 2,496
|
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:
You might achieve a similar advantage when you store the single digits of your score, and write a simple addition function for it. Quote:
|
||
25 April 2020, 01:21 | #6 |
Registered User
Join Date: Mar 2012
Location: UK
Posts: 1,893
|
|
25 April 2020, 01:22 | #7 | |
Registered User
Join Date: Mar 2012
Location: UK
Posts: 1,893
|
Quote:
|
|
25 April 2020, 01:23 | #8 |
Registered User
Join Date: Mar 2012
Location: UK
Posts: 1,893
|
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 |
Registered User
Join Date: Jul 2015
Location: The Netherlands
Posts: 3,408
|
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:
With that in mind, let me offer an two alternative ways of thinking about optimising the score display - neither of which remove divisions
|
25 April 2020, 11:30 | #10 |
This cat is no more
Join Date: Dec 2004
Location: FRANCE
Age: 52
Posts: 8,161
|
@roondar, then check Andrew Braybook games
|
25 April 2020, 11:39 | #11 |
Registered User
Join Date: Jul 2015
Location: The Netherlands
Posts: 3,408
|
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 | |
Registered User
Join Date: Mar 2012
Location: UK
Posts: 1,893
|
Quote:
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 In addition - 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 |
This cat is no more
Join Date: Dec 2004
Location: FRANCE
Age: 52
Posts: 8,161
|
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 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 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 | |||
Registered User
Join Date: Jul 2015
Location: The Netherlands
Posts: 3,408
|
Quote:
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:
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:
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 |
This cat is no more
Join Date: Dec 2004
Location: FRANCE
Age: 52
Posts: 8,161
|
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 |
Phone Homer
Join Date: Jun 2006
Location: 5150
Posts: 5,773
|
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 | |
Banana
Join Date: Jul 2016
Location: Darmstadt
Posts: 1,213
|
Quote:
https://eab.abime.net/showpost.php?p...1&postcount=27 |
|
28 April 2020, 23:30 | #18 |
Registered User
Join Date: Mar 2012
Location: UK
Posts: 1,893
|
WIP in progress now in the zone.
Please feel free to let me know you thoughts... http://eab.abime.net/zone/Flappy.adf |
31 July 2020, 18:28 | #19 |
Registered User
Join Date: Mar 2012
Location: UK
Posts: 1,893
|
|
Currently Active Users Viewing This Thread: 1 (0 members and 1 guests) | |
Thread Tools | |
Similar Threads | ||||
Thread | Thread Starter | Forum | Replies | Last Post |
Only 4 ways to score in Sensible Soccer? | twenty90seven | support.Games | 6 | 23 January 2015 02:19 |
Hard Blits under intuition & Gif To "struct BitMap" converter | krabob | Coders. Asm / Hardware | 2 | 15 September 2014 17:25 |
Renaming Hi-Score Files | cybernoid | project.WHDLoad | 14 | 01 July 2008 09:32 |
What's the biggest score you've ever seen? | girv | Retrogaming General Discussion | 33 | 17 August 2007 23:50 |
Hi-score section | Shatterhand | project.EAB | 6 | 29 March 2003 10:28 |
|
|