+mksmith Posted July 6, 2020 Share Posted July 6, 2020 Hi everyone, I'm going to list some tricks, tips and examples for using 7800basic. Many have also been generously offered by Mike @RevEng and Lewis @Muddyfunster. I'll provide a Table of Contents so they will be easy to find as I add them or have questions about them. Display, Sprites and Images Clear Palette Clear Palette (Double-Buffer) Sprite Animation TallSprite [Updated] Quick Score [Updated] Centering Text Singlewide Text in Doublewide Mode [Updated] Sound Copy TIA Sound to Ram Controls Read Controller Data/Tables Large Data Table > 256 Bytes 7 4 Quote Link to comment https://forums.atariage.com/topic/308806-7800basic-tips-tricks-and-examples/ Share on other sites More sharing options...
+mksmith Posted July 6, 2020 Author Share Posted July 6, 2020 Clear Palette I have found particularly as you change screen between banks it's a great idea to total black the display BEFORE changing banks otherwise you can have screen and color artefacting issues as you switching to the next screen. For example your Title Screen in bank 7 and the user presses the button to start the game. This may result in you returning to bank 1 to initialise your game and begin the gameplay (either in bank 1 or another bank). A call to this function (I keep this in the last shared bank) will ensure screen artefacting is kept to a minimum before your next screen is built. ClearPalette rem background BACKGRND = $00 rem palettes P0C1 = $00 : P0C2 = $00 : P0C3 = $00 P1C1 = $00 : P1C2 = $00 : P1C3 = $00 P2C1 = $00 : P2C2 = $00 : P2C3 = $00 P3C1 = $00 : P3C2 = $00 : P3C3 = $00 P4C1 = $00 : P4C2 = $00 : P4C3 = $00 P5C1 = $00 : P5C2 = $00 : P5C3 = $00 P6C1 = $00 : P6C2 = $00 : P6C3 = $00 P7C1 = $00 : P7C2 = $00 : P7C3 = $00 rem screen clearscreen : savescreen : drawscreen return 4 Quote Link to comment https://forums.atariage.com/topic/308806-7800basic-tips-tricks-and-examples/#findComment-4579898 Share on other sites More sharing options...
+mksmith Posted July 6, 2020 Author Share Posted July 6, 2020 Read Controller Keeping track of what controllers you are accessing can depending on the game be a little tricky at times. 7800basic offers access to various controllers such as 1 or 2 button joysticks, paddles, driving wheels and mice and these can be easily configured. But what about tracking things such as debounce, button press/held states or multiple controls where might be easier to do a single check? As I developed Arkanoid I needed to to find ways to track all these things so I came up with a single function I call at the start of each frame. I can then check the status of some bits to do most of the work for me. You can expand these functions with additional checks for things such as paddle buttons or for 1 button joysticks tag both buttons as pressed as I have done in Arkanoid to allow the use of both the laser and slower vaus speeds. Basic rem controller dirs dim controllerState = var0 dim controller_debounce_bit0 = var0 dim controller_left_bit1 = var0 dim controller_right_bit2 = var0 dim controller_up_bit3 = var0 dim controller_down_bit4 = var0 rem controller buttons dim controllerButtonState = var1 dim controller_button_debounce_bit0 = var1 dim controller_button1_press_bit1 = var1 dim controller_button2_press_bit4 = var1 ReadController rem clear (don't touch debounce state) controllerState = controllerState&%00000001 controllerButtonState = controllerButtonState&%00000001 rem joystick if !joy0any then goto _readControllerSkipJoystickDirectionCheck if joy0left then controller_left_bit1{1} = 1 if joy0right then controller_right_bit2{2} = 1 if joy0up then controller_up_bit3{3} = 1 if joy0down then controller_down_bit4{4} = 1 _readControllerSkipJoystickDirectionCheck rem left port rem button 1 press if joy0fire1 then controller_button1_press_bit1{1} = 1 rem button 2 press if joy0fire0 then controller_button2_press_bit4{4} = 1 rem clear debounce? (nothing chosen) if controllerState = %00000001 then controller_debounce_bit0{0} = 0 if controllerButtonState = %00000001 then controller_button_debounce_bit0{0} = 0 rem exit return Advanced This advanced function adds additional tracking for determining whether a player is quickly tapping a button, pressing a button (this is your general check) or holding down a button. I needed to determine in Millie and Molly whether the player was tapping the button (switch between Millie and Molly) or holding the button (activate the rewind feature). rem controller dirs dim controllerState = var0 dim controller_debounce_bit0 = var0 dim controller_left_bit1 = var0 dim controller_right_bit2 = var0 dim controller_up_bit3 = var0 dim controller_down_bit4 = var0 rem controller buttons dim controllerButtonState = var1 dim controller_button_debounce_bit0 = var1 dim controller_button1_press_bit1 = var1 dim controller_button1_tap_bit2 = var1 dim controller_button1_hold_bit3 = var1 dim controller_button2_press_bit4 = var1 dim controller_button2_tap_bit5 = var1 dim controller_button2_hold_bit6 = var1 rem controller button held counter dim controller_button1_counter = var2 dim controller_button2_counter = var3 ReadController rem clear (don't touch debounce state) controllerState = controllerState&%00000001 controllerButtonState = controllerButtonState&%00000001 rem joystick if !joy0any then goto _readControllerSkipJoystickDirectionCheck if joy0left then controller_left_bit1{1} = 1 if joy0right then controller_right_bit2{2} = 1 if joy0up then controller_up_bit3{3} = 1 if joy0down then controller_down_bit4{4} = 1 _readControllerSkipJoystickDirectionCheck rem left port rem button 1 press if joy0fire1 then controller_button1_press_bit1{1} = 1 rem button 2 press if joy0fire0 then controller_button2_press_bit4{4} = 1 rem increment button counters? if controller_button1_press_bit1{1} then controller_button1_counter = controller_button1_counter+1 : if controller_button1_counter > 99 then controller_button1_counter = 99 if controller_button2_press_bit4{4} then controller_button2_counter = controller_button2_counter+1 : if controller_button2_counter > 99 then controller_button2_counter = 99 rem change the value 15 to lengthen or shorten the tap/hold rem button hold? if controller_button1_counter > 15 then controller_button1_hold_bit3{3} = 1 if controller_button2_counter > 15 then controller_button2_hold_bit6{6} = 1 rem button tap? if !controller_button1_press_bit1{1} && controller_button1_counter > 0 && controller_button1_counter <= 15 then controller_button1_tap_bit2{2} = 1 if !controller_button2_press_bit4{4} && controller_button2_counter > 0 && controller_button2_counter <= 15 then controller_button2_tap_bit5{5} = 1 rem clear counters if !controller_button1_press_bit1{1} then controller_button1_counter = 0 if !controller_button2_press_bit4{4} then controller_button2_counter = 0 rem clear debounce? (nothing chosen) if controllerState = %00000001 then controller_debounce_bit0{0} = 0 if controllerButtonState = %00000001 then controller_button_debounce_bit0{0} = 0 rem exit return Example Here is a basic Main Loop example where a player could move left/right and press a button. Using the debounce flags they will need to release the joystick to register before they can register another direction or button change (signified by the sound effect) set romsize 48k rem controller dirs dim controllerState = var0 dim controller_debounce_bit0 = var0 dim controller_left_bit1 = var0 dim controller_right_bit2 = var0 dim controller_up_bit3 = var0 dim controller_down_bit4 = var0 rem controller buttons dim controllerButtonState = var1 dim controller_button_debounce_bit0 = var1 dim controller_button1_press_bit1 = var1 dim controller_button2_press_bit4 = var1 MainLoopInitialise rem set debounce states controller_debounce_bit0{0} = 1 : controller_button_debounce_bit0{0} = 1 MainLoop rem controls gosub ReadController rem check joystick rem is the player currently moving in a direction or pressing a button? if so skip if controller_debounce_bit0{0} || controller_button_debounce_bit0{0} then goto _mainLoopSkipJoystickCheck rem check directions rem if the player is moving in a direction set the debounce flag so they need release the joystick to continue move again if controller_left_bit1{1} then controller_debounce_bit0{0} = 1 : playsfx sfx_ding 7 : BACKGRND = rand if controller_right_bit2{2} then controller_debounce_bit0{0} = 1 : playsfx sfx_ding 9 : BACKGRND = rand if controller_up_bit3{3} then controller_debounce_bit0{0} = 1 : playsfx sfx_ding 8 : BACKGRND = rand if controller_down_bit4{4} then controller_debounce_bit0{0} = 1 : playsfx sfx_ding 6 : BACKGRND = rand rem check buttons rem if the player is pressing a button set the debounce flag so they need to release the button to fire again rem button? if controller_button1_press_bit1{1} then controller_button_debounce_bit0{0} = 1 : playsfx sfx_fire 6 : BACKGRND = rand _mainLoopSkipJoystickCheck rem draw clearscreen rem ... drawscreen rem continue goto MainLoop ReadController rem clear (don't touch debounce state) controllerState = controllerState&%00000001 controllerButtonState = controllerButtonState&%00000001 rem joystick if !joy0any then goto _readControllerSkipJoystickDirectionCheck if joy0left then controller_left_bit1{1} = 1 if joy0right then controller_right_bit2{2} = 1 if joy0up then controller_up_bit3{3} = 1 if joy0down then controller_down_bit4{4} = 1 _readControllerSkipJoystickDirectionCheck rem left port rem button 1 press if joy0fire1 then controller_button1_press_bit1{1} = 1 rem button 2 press if joy0fire0 then controller_button2_press_bit4{4} = 1 rem clear debounce? (nothing chosen) if controllerState = %00000001 then controller_debounce_bit0{0} = 0 if controllerButtonState = %00000001 then controller_button_debounce_bit0{0} = 0 rem exit return data sfx_ding 16, 0, 1; version, priority, frames per chunk $01,$04,$08 ; 1st chunk of freq,channel,volume data $01,$04,$04; 2nd chunk $01,$04,$07 ; 1st chunk of freq,channel,volume data $01,$04,$03; $01,$04,$06 ; 3rd chunk $01,$04,$02 ; 4th chunk $01,$04,$05 ; 1st chunk of freq,channel,volume data $01,$04,$01; $01,$04,$04 ; 5th chunk $01,$04,$00 $01,$04,$03 ; 1st chunk of freq,channel,volume data $01,$04,$00; $01,$04,$02 ; 1st chunk of freq,channel,volume data $01,$04,$00; $01,$04,$01 ; 1st chunk of freq,channel,volume data $01,$04,$00; $00,$00,$00 ; End Of Sound marker end data sfx_fire 16, 1, 1; version, priority, frames per chunk $01,$0c,$08 ; 1st chunk of freq,channel,volume data $07,$0c,$08; 2nd chunk $09,$0c,$08 ; 1st chunk of freq,channel,volume data $0b,$0c,$08 $01,$0c,$04; 1st chunk of freq,channel,volume data $07,$0c,$04; 2nd chunk $09,$0c,$04 $0b,$0c,$04 $01,$0c,$02 ; 1st chunk of freq,channel,volume data $07,$0c,$02; 2nd chunk $09,$0c,$02 $0b,$0c,$02 $00,$00,$00 end Tips Before entering a new screen such as a title or game over screen where you check for a button press, set the debounce flags before starting your screen loop. That way you don't skip through the screen if the player is still holding down the button from the prior screen. controller_debounce_bit0{0} = 1 : controller_button_debounce_bit0{0} = 1 4 Quote Link to comment https://forums.atariage.com/topic/308806-7800basic-tips-tricks-and-examples/#findComment-4579905 Share on other sites More sharing options...
+mksmith Posted July 6, 2020 Author Share Posted July 6, 2020 Copy TIA sound into RAM Sound effects can add a lot your game but as your game grows you may require the same sound to be played from within a number of banks. There are a couple of options: Store the sound effect data in your last shared bank so it can be called from anywhere Duplicate the sound effect data in each of the required banks (using different names to identify them ie. sfx_vaus_laser_bank1, sfx_vaus_laser_bank2) Depending on the size of your game one or both of these options may not be available. They way I lay my games out with Bank 1 being the entry bank it doesn't really get used for much other than initialisation tasks and as a returning point when switching between screens such as the splash, title, intro and game. I often store sound effects in the last shared bank (Bank 8 ) but when you have quite a few things in there to share it quickly becomes full. Whilst I have started duplicating code in banks (another great trick!) I try where possible to not duplicate stuff such as sound effects. Example Recently I have started using Bank 1 to store things I can copy into shared RAM leaving me with valuable space in Bank 8 but still having it accessible from anywhere. set romsize 128k rem vars dim buttonDebounce = var0 rem configure RAM location for sound dim SFXVAUSLASERADR = $2300 rem copy TIA sound to RAM gosub CopyTIASoundToRamBank1 rem set buttonDebounce = 0 rem start goto MainLoopBank2 bank2 CopyTIASoundToRamBank1 memcpy SFXVAUSLASERADR sfx_vaus_laser $2a return data sfx_vaus_laser 16, 1, 1; version, priority, frames per chunk $01,$0c,$08 ; 1st chunk of freq,channel,volume data $07,$0c,$08; 2nd chunk $09,$0c,$08 ; 1st chunk of freq,channel,volume data $0b,$0c,$08 $01,$0c,$04; 1st chunk of freq,channel,volume data $07,$0c,$04; 2nd chunk $09,$0c,$04 $0b,$0c,$04 $01,$0c,$02 ; 1st chunk of freq,channel,volume data $07,$0c,$02; 2nd chunk $09,$0c,$02 $0b,$0c,$02 $00,$00,$00 end rem -------------------------------------------------------------------------- rem BANK2 rem -------------------------------------------------------------------------- bank 2 MainLoopBank2 rem button? if buttonDebounce then goto _mainLoopBank2SkipButtonCheck if joy0fire1 then buttonDebounce = 1 : playsfx SFXVAUSLASERADR 6 : BACKGRND = rand _mainLoopBank2SkipButtonCheck rem clear debounce if !joy0fire1 then buttonDebounce = 0 rem draw clearscreen rem ... drawscreen rem continue goto MainLoopBank2 Dev Notes This is an advanced technique which should only be used where you are using a multi-bank ROM and understand the appropriate RAM location to store your data. 6 Quote Link to comment https://forums.atariage.com/topic/308806-7800basic-tips-tricks-and-examples/#findComment-4579917 Share on other sites More sharing options...
+Karl G Posted July 6, 2020 Share Posted July 6, 2020 Thanks for sharing these tips! One question though: why or how would switching banks mess up the display or colors? 1 Quote Link to comment https://forums.atariage.com/topic/308806-7800basic-tips-tricks-and-examples/#findComment-4579944 Share on other sites More sharing options...
SlidellMan Posted July 6, 2020 Share Posted July 6, 2020 Hey, thanks for the clever tricks. Maybe you could give tips on how to make bosses that are comprised of several sprites? 1 Quote Link to comment https://forums.atariage.com/topic/308806-7800basic-tips-tricks-and-examples/#findComment-4579974 Share on other sites More sharing options...
RevEng Posted July 6, 2020 Share Posted July 6, 2020 2 hours ago, Karl G said: Thanks for sharing these tips! One question though: why or how would switching banks mess up the display or colors? The 7800basic game code runs during the visible screen, to maximize the number of cycles available to the game. If you include your graphics into a switchable bank, then bank-switching to another bank will cause the graphics rom to be replaced with whatever is at your bankswitch destination. Maria doesn't understand bank-switching, so it has no way to get to your pre-bankswitch graphics. (outside of exotic bank-switching schemes, anyway) To avoid glitching in these circumstances, you can either: place your graphics in a perma-bank (which has limited space) put a copy of the graphics in your source bank at the destination bank call "drawwait" before your bankswitch and be sure to return before the next visible screen begins (which wastes the visible cycles) If you're swapping between different kinds of levels or screens, you can just black all the palettes so no graphics are visible (as Matt has demonstrated) as you build the new screen. As a minor bit of compensation, you can also use this bankswitch graphics-swap effect to skin levels. 3 3 Quote Link to comment https://forums.atariage.com/topic/308806-7800basic-tips-tricks-and-examples/#findComment-4579979 Share on other sites More sharing options...
+Muddyfunster Posted July 6, 2020 Share Posted July 6, 2020 (edited) @RevEng Thanks for the explanation on the colour artifacts I figured it was something like " "Maria says so!". I was using something similar to Matt's technique to stop artifacts in EXO (dimming down when changing screen across banks to avoid that splash of colour from the previous screen), but I found when I moved to double buffering it doesn't work, I guess due to how double buffing builds the screen. I've not yet figured a workaround, but that's a lower priority fix for me. @mksmith This is great Matt, assume it's ok to share code snips as well for the thread? Would be nice to build up the kind of knowledge base we have for Bb. Edited July 6, 2020 by Muddyfunster 4 Quote Link to comment https://forums.atariage.com/topic/308806-7800basic-tips-tricks-and-examples/#findComment-4580002 Share on other sites More sharing options...
+mksmith Posted July 6, 2020 Author Share Posted July 6, 2020 7 hours ago, SlidellMan said: Hey, thanks for the clever tricks. Maybe you could give tips on how to make bosses that are comprised of several sprites? Definitely can put something together there - I intend on adding some tips around sprites, tallsprites and animations ? @Karl G @RevEng thanks for explaining that Mike - I was struggling to explain that one in a way that was clear enough to understand. That is the general use case I have seen the artefacting. @Muddyfunster of course mate ? 3 1 Quote Link to comment https://forums.atariage.com/topic/308806-7800basic-tips-tricks-and-examples/#findComment-4580318 Share on other sites More sharing options...
+mksmith Posted July 8, 2020 Author Share Posted July 8, 2020 (edited) Sprite Animation Most games will require some sort of sprite animations eg. players, enemies, bullets, explosions etc. Depending on your requirements there are many ways to achieve this. Example 1 (Simple increment) Simple increment of a frame tracking index will update the animation each frame. To repeat the animation we check for the last frame and reset the index back to 0. rem vars dim frameIndex = var0 rem increment frame frameIndex = frameIndex + 1 : if frameIndex > 12 then frameIndex = 0 rem draw plotsprite frame0 0 70 94 frameIndex Example 2 (Advanced increment and speed control) What if we want to control the speed of the animation? There are 2 options do this: Example 2A - Using a delay variable Say you want to change the animation every x number of frames rather than every frame as in example 1? A delay counter introduces the ability to determine the speed of the animation: rem vars dim frameIndex = var0 dim frameDelayCounter = var1 rem increment frame (speed) frameDelayCounter = frameDelayCounter + 1 : if frameDelayCounter > 9 then frameDelayCounter = 0 : frameIndex = frameIndex + 1 if frameIndex > 12 then frameIndex = 0 rem draw plotsprite frame0 0 70 94 frameIndex Example 2B - Using fixed point variables Rather than using a delay counter you can instead simplify the delay by using a fixed point variable: rem vars dim frameIndex = var0.var1 rem increment frame (speed) frameIndex = frameIndex + 0.1 : if frameIndex > 12 then frameIndex = 0 rem draw plotsprite frame0 0 70 94 frameIndex Depending on your requirements either of these options can be used and each has potential advantages and disadvantages. Example 3 (Animation list) There are also times you may want a finer control over your animation rather than using a simple repeating loop. What if we wanted a ping-pong style loop or to use only specific frames in our animation? We can use a lookup list to determine which animation frame we want shown: rem vars dim frameIndex = var0.var1 dim animationFrame = var2 rem list of frames to animate data frameAnimationList 1,2,3,4,5,6,7,8,9,10,11,12,11,10,9,8,7,6,5,4,3,2 end rem increment frame (speed) frameIndex = frameIndex + 0.25 : if frameIndex > 21 then frameIndex = 0 rem lookup frame from animation list animationFrame = frameAnimationList[frameIndex] rem draw plotsprite frame0 0 70 94 animationFrame Full examples The following attachment contains full working examples for the above: SpriteAnimation.zip Dev Notes The sprite_graphic property in the plotsprite command should refer to the first frame in the animation (it is recommended you incgraphic your frames in the base order of the animation) When using the frame property in the plotsprite command you must ensure all frames within that animation exist in the same GFX Block otherwise the animation will display the incorrect frame. Additional consideration is also required where you are using TallSprites. PLOTSPRITE command plotsprite sprite_graphic palette_# x y [frame] [tallheight] sprite_graphic - name of the included graphic palette_# - index of palette (0-7) x - x screen co-ordinate y - y screen co-ordinate frame (optional) - index of the frame to display tallheight (optional) - number of zones each tallsprite occupies Edited December 1, 2020 by mksmith Updated for changes in 7800basic 6 Quote Link to comment https://forums.atariage.com/topic/308806-7800basic-tips-tricks-and-examples/#findComment-4581175 Share on other sites More sharing options...
+mksmith Posted July 9, 2020 Author Share Posted July 9, 2020 (edited) Tall Sprites Continuing on from the sprite animation, tall sprites work effectively the same (with some minor changes as you will see) but allow you to automatically display sprites much larger than your base zone-height (8 or 16 pixels) taking away a lot of complexity. The key changes here is setting the tallsprite flag and then when plotting the sprite confirming the zone-height of your sprite and calculating an offset to the start of the next frame. All of these are very simple into implement. Update (7800basic v0.16 onwards) From this version onwards you no longer need to calculate the offset to the next frame as 7800basic now does this for you! If you wish to keep compatibility with your existing source but utilise newer versions of 7800basic, add the following line to the configuration at the top of your source: set deprecated frameheight Configuring tall sprites To use tallsprites all you need to do is activate the setting in your configuration at the top of your source. This will inform 7800basic to join all incgraphic images greater than the zone-height together. set tallsprite on Example 1 (7800basic v0.15 or earlier) The additional change over our base animation is determining the frame animation offset. To do this we need to know how tall our sprite is in relation to the number of zones we have configured. In our example below we have set an 8 zone-height and our sprite is 24 pixels high - thus our count is 24/8 = 3. So to calculate our offset we need to multiply the current frameIndex by 3 and in the plotsprite function set frame property to our offset and set the count property to 3 (the number of actual sprites that make up our image). set zoneheight 8 set tallsprite on rem vars dim frameIndex = var0.var1 dim frameAnimationOffset = var2 rem increment frame (speed) frameIndex = frameIndex + 0.20 : if frameIndex > 5 then frameIndex = 0 rem calculate next frame offset frameAnimationOffset = frameIndex*3 rem draw plotsprite frame0 0 70 88 frameAnimationOffset 3 Full example The following attachment contains a fully working example: tallsprite.zip Example 2 (7800basic v0.16 or later) As we no longer need to calculate the frame offset, the process is simplified: set zoneheight 8 set tallsprite on rem vars dim frameIndex = var0.var1 rem increment frame (speed) frameIndex = frameIndex + 0.20 : if frameIndex > 5 then frameIndex = 0 rem draw plotsprite frame0 0 70 88 frameIndex Full example The following attachment contains a fully working example: tallsprite_new.zip Dev Notes When using tallsprites the height of your sprite should always follow the expected zone-height boundaries. So for a zone-height of 8 your sprite height should follow 8,16,24,32 etc pixels whilst for a 16 zone-height sprite 16,32,48,64 pixels etc As with standard height sprites when using the frame property in plotsprite you must ensure all frames within that animation exist in the same GFX Block otherwise the animation will display the incorrect frame One way to determine if the tallsprite feature is active is to review your GFX Block allocations in the compile log. Each tallsprite imported will be tagged with the _tallsprite_xx allocation. PLOTSPRITE command plotsprite sprite_graphic palette_# x y [frame] [tallheight] sprite_graphic - name of the included graphic palette_# - index of palette (0-7) x - x screen co-ordinate y - y screen co-ordinate frame (optional) - index of the frame to display tallheight (optional) - number of zones each tallsprite occupies Edited December 1, 2020 by mksmith Updated for changes in 7800basic 6 Quote Link to comment https://forums.atariage.com/topic/308806-7800basic-tips-tricks-and-examples/#findComment-4581789 Share on other sites More sharing options...
+mksmith Posted July 9, 2020 Author Share Posted July 9, 2020 Quick Score (Advanced) This is an advanced feature and it's use may vary depending on the type of game you are creating. This is one shared to me by @RevEng and allows you to update your score display without having to continually render the output with plotchars/plotvalue each frame, which can be quite costly to your display time. In effect we end up modifying already-plotted DL objects (by baking the object into our screen with a "savescreen") from RAM. Some further general information about this type of process is available in Mike's 7800basic, under the hood post. Update An additional example has been added which caters for doublewide on mode where characters as 8 pixels wide (2x4) rather than the standard 4 pixels. Thanks again to Mike for the required changes. Configuration For a six-digit display we create some RAM variables (scoreText vars) to store the score digits and then use the textdata parameter in the plotchars command to draw those into our display (starting at the first variable). The scoreVar variables are used to split the score into bytes allowing us to quickly update the RAM store. rem vars dim scoreText0 = var0 dim scoreText1 = var1 dim scoreText2 = var2 dim scoreText3 = var3 dim scoreText4 = var4 dim scoreText5 = var5 dim scoreVar0 = score0 dim scoreVar1 = score0+1 dim scoreVar2 = score0+2 InitialiseScreen clearscreen rem bake score display into buffer plotchars '1up' 1 20 0 3 plotchars scoreText0 0 12 1 6 savescreen return Once your display is configured it's a matter of copying the score in the RAM variables either every frame (recommended) or as the score is updated. Depending on whether you are using standard or doublewide character modes, use one of the following: Standard character mode (4 pixel characters) UpdateScore rem replace chars with score scoreText5 = scoreVar2&$0F scoreText4 = scoreVar2/16 scoreText3 = scoreVar1&$0F scoreText2 = scoreVar1/16 scoreText1 = scoreVar0&$0F scoreText0 = scoreVar0/16 return Doublewide character mode (8 pixel characters - 2x4) UpdateScore rem replace chars with score scoreText5 = (scoreVar2&$0F)*2 scoreText4 = (scoreVar2/16)*2 scoreText3 = (scoreVar1&$0F)*2 scoreText2 = (scoreVar1/16)*2 scoreText1 = (scoreVar0&$0F)*2 scoreText0 = (scoreVar0/16)*2 return Updating the score To change the score you just update your score0 variable as per normal: score0 = score0 + 250 Full examples The following attachment contains a fully working examples: QuickScore.zip QuickScore_DoubleWide.zip PLOTCHARS command plotchars textdata palette_# x y [chars|extrawide] textdata - RAM, ROM or literal string 'message' to plot onto the screen palette_# - index of palette (0-7) x - x screen co-ordinate y - y line (zone) co-ordinate chars (optional) - number of characters to display extrawide (optional) - display chars twice the width of the character size 5 Quote Link to comment https://forums.atariage.com/topic/308806-7800basic-tips-tricks-and-examples/#findComment-4581817 Share on other sites More sharing options...
SlidellMan Posted July 12, 2020 Share Posted July 12, 2020 I wonder how many TIA Sound effects can be stored in each bank? 1 Quote Link to comment https://forums.atariage.com/topic/308806-7800basic-tips-tricks-and-examples/#findComment-4584288 Share on other sites More sharing options...
+mksmith Posted July 14, 2020 Author Share Posted July 14, 2020 On 7/13/2020 at 8:13 AM, SlidellMan said: I wonder how many TIA Sound effects can be stored in each bank? Hi! That certainly depends on your code requirements. I certainly had no chance to include any in Millie and Molly and am finding not likely for Arkanoid - one of the reasons I needed this feature for this game. There is definitely a real balance in your main game bank ? 2 Quote Link to comment https://forums.atariage.com/topic/308806-7800basic-tips-tricks-and-examples/#findComment-4585263 Share on other sites More sharing options...
+Muddyfunster Posted July 14, 2020 Share Posted July 14, 2020 On 7/6/2020 at 12:41 PM, mksmith said: Clear Palette I have found particularly as you change screen between banks it's a great idea to total black the display BEFORE changing banks otherwise you can have screen and color artefacting issues as you switching to the next screen. For example your Title Screen in bank 7 and the user presses the button to start the game. This may result in you returning to bank 1 to initialise your game and begin the gameplay (either in bank 1 or another bank). A call to this function (I keep this in the last shared bank) will ensure screen artefacting is kept to a minimum before your next screen is built. ClearPalette rem background BACKGRND = $00 rem palettes P0C1 = $00 : P0C2 = $00 : P0C3 = $00 P1C1 = $00 : P1C2 = $00 : P1C3 = $00 P2C1 = $00 : P2C2 = $00 : P2C3 = $00 P3C1 = $00 : P3C2 = $00 : P3C3 = $00 P4C1 = $00 : P4C2 = $00 : P4C3 = $00 P5C1 = $00 : P5C2 = $00 : P5C3 = $00 P6C1 = $00 : P6C2 = $00 : P6C3 = $00 P7C1 = $00 : P7C2 = $00 : P7C3 = $00 rem screen clearscreen : savescreen return You can use almost the same code if you are doublebuffering the display. I found forcing a restorescreen and then a doublebuffer flip worked well and prevented artifacts in exactly the same way as Matt's code. In EXO I'm retrieving screens stored in another bank so I'm going between banks on each screen change. This method eliminates artifacts and colour ghosts (where the colours remain plotted for a frame the same as the previous screen before Maria catches up - it looks "rough" if you have contrasting colours without a dimming routine). Clear_Palette BACKGRND = $00 P0C1 = $00 : P0C2 = $00 : P0C3 = $00 P1C1 = $00 : P1C2 = $00 : P1C3 = $00 P2C1 = $00 : P2C2 = $00 : P2C3 = $00 P3C1 = $00 : P3C2 = $00 : P3C3 = $00 P4C1 = $00 : P4C2 = $00 : P4C3 = $00 P5C1 = $00 : P5C2 = $00 : P5C3 = $00 P6C1 = $00 : P6C2 = $00 : P6C3 = $00 P7C1 = $00 : P7C2 = $00 : P7C3 = $00 clearscreen savescreen restorescreen doublebuffer flip return 3 Quote Link to comment https://forums.atariage.com/topic/308806-7800basic-tips-tricks-and-examples/#findComment-4585418 Share on other sites More sharing options...
SlidellMan Posted July 14, 2020 Share Posted July 14, 2020 That's really clever, Muddyfunster! 1 Quote Link to comment https://forums.atariage.com/topic/308806-7800basic-tips-tricks-and-examples/#findComment-4585655 Share on other sites More sharing options...
+mksmith Posted July 14, 2020 Author Share Posted July 14, 2020 Great stuff Lewis ? 1 Quote Link to comment https://forums.atariage.com/topic/308806-7800basic-tips-tricks-and-examples/#findComment-4585684 Share on other sites More sharing options...
+Muddyfunster Posted July 15, 2020 Share Posted July 15, 2020 (edited) Easy centering of text Sometimes you want to have centered text rather than left justified, like on a menu or something. An easy way to work out the PLOTCHAR co-ordinates : Step 1 - calculate the length of text you want to plot including spaces Step 2 - multiply by the font type (x4 for a 4 pixel wide font, x8 for an 8 pixel wide font) Step 3 - divide this by 2 Step 4 - take this remaining number away from 80 (80 being the middle of the screen) result is your x co-ordinate to center the plotchar. Example. I want to center the text "GAME MENU" Step 1 - length = 9 (8 letters + 1 space) Step 2 - 8 pixel font so 9*8 = 72 Step 3 - 72 / 2 = 36 Step 4 - 80-36 = 44 result : our x co-ordinate to horizontally center "GAME MENU" is 44. plotchar 'GAME MENU' 0 44 0 I've also added an excel and opendoc file that does the calculation for you. These are provided "as-is". Hope this is useful ! plotchar calc.ods plotchar calc.xlsx Edited July 15, 2020 by Muddyfunster 5 Quote Link to comment https://forums.atariage.com/topic/308806-7800basic-tips-tricks-and-examples/#findComment-4586066 Share on other sites More sharing options...
+mksmith Posted July 15, 2020 Author Share Posted July 15, 2020 Thanks @Muddyfunster- that's a really handy spreadsheet! 1 Quote Link to comment https://forums.atariage.com/topic/308806-7800basic-tips-tricks-and-examples/#findComment-4586069 Share on other sites More sharing options...
SlidellMan Posted July 15, 2020 Share Posted July 15, 2020 That's quite clever, Muddy, and reminds me of why I did those mockups. 1 Quote Link to comment https://forums.atariage.com/topic/308806-7800basic-tips-tricks-and-examples/#findComment-4586510 Share on other sites More sharing options...
Lillapojkenpåön Posted October 1, 2020 Share Posted October 1, 2020 I copied quickscore to my code, what am I doing wrong if plotchars '1up' 3 20 3 3 ;shows up as 23 ]& plotchars scoreText0 3 12 3 6 ;doesn't show up at all? 1 Quote Link to comment https://forums.atariage.com/topic/308806-7800basic-tips-tricks-and-examples/#findComment-4644222 Share on other sites More sharing options...
Mord Posted October 1, 2020 Share Posted October 1, 2020 3 hours ago, Lillapojkenpåön said: I copied quickscore to my code, what am I doing wrong if plotchars '1up' 3 20 3 3 ;shows up as 23 ]& plotchars scoreText0 3 12 3 6 ;doesn't show up at all? The quickscore code was a complete sample program. If you copied the entire thing to your own code there's possibly conflicts in the dims and characterset/imports going on? Compiling the example.78b on it's own gives a proper output. If you're using your own font, it would have to be designed similarly to what's in the example (digits first in particular.) I believe the example also requires the digits/fonts to be added to the bank first so the math will hold up, if you have other graphics being added. In the example there's only the 1 graphic/font being included anyway. 1 1 Quote Link to comment https://forums.atariage.com/topic/308806-7800basic-tips-tricks-and-examples/#findComment-4644293 Share on other sites More sharing options...
+mksmith Posted October 1, 2020 Author Share Posted October 1, 2020 Thanks Mord ? Quote Link to comment https://forums.atariage.com/topic/308806-7800basic-tips-tricks-and-examples/#findComment-4644336 Share on other sites More sharing options...
Lillapojkenpåön Posted October 1, 2020 Share Posted October 1, 2020 8 hours ago, Mord said: The quickscore code was a complete sample program. If you copied the entire thing to your own code there's possibly conflicts in the dims and characterset/imports going on? Compiling the example.78b on it's own gives a proper output. If you're using your own font, it would have to be designed similarly to what's in the example (digits first in particular.) Thanks, I'm using the same font, at first the screen was completely scrambled, so I did the characterset right before when they were needed characterset testsprite plotmap tiledMap4colors 0 0 0 20 12 0 0 40 plotmap tiledMap4colors 0 80 0 20 12 20 0 40 characterset font plotchars '1up' 3 20 3 3 plotchars scoreText0 3 12 4 6 That made the background good but not the font apparently, do I need to re-draw the font in my tileset and only do one characterset or can I use it like I do? 8 hours ago, Mord said: I believe the example also requires the digits/fonts to be added to the bank first so the math will hold up, if you have other graphics being added. In the example there's only the 1 graphic/font being included anyway. I don't understand what you mean, "added to the bank" especially? Could you try to explain in other words? I tried doing the incgraphic font.png 160A first thing in my code that made the 6 digits show up, 010101, then I changed 160A to 160B in the incgraphic, and that made the text say 1up but now only shows the first 3 digits, 000, So it's allmost working now, except only 3 digits? I tried to change 1up to "score" but it also only shows first 3 letters, I both changed the number_of_chars parameter and removed it, no luck. Quote Link to comment https://forums.atariage.com/topic/308806-7800basic-tips-tricks-and-examples/#findComment-4644600 Share on other sites More sharing options...
Mord Posted October 1, 2020 Share Posted October 1, 2020 2 hours ago, Lillapojkenpåön said: I don't understand what you mean, "added to the bank" especially? Could you try to explain in other words? Any time you're adding a graphic to your program with incgraphic, you're "adding it to the bank". IE: a graphics bank. So by adding it to the bank first I just mean make sure it's the first incgraphic command you add. You shouldn't need to be switching it to 160B given the font being used in the example is expecting 160A sized sprites - 160B sprites are basically half the size of a 160A sprite. (a 2 byte 160A sprite is 8 pixels, a 2 byte 160B sprite is 4 pixels) What you should be seeing, instead of 3 digits, is 6 half-digits (the left hand side of each digit). The 1's might not be showing anything if the left hand is blank, or perhaps they're looking like the rest of the zero from the digit before them? For the characterset, if both font.png and testsprite.png are in the same graphics bank then you should be able to just use "characterset font". I'm not sure what the effect of using multiple characterset commands in the program would be or if it's even suppose to be possible. Also, perhaps change it back to 160A first, then take a look at what values you're giving to palette P3. Maybe it's displaying but with the palette is set to the same color as the background color? 1 Quote Link to comment https://forums.atariage.com/topic/308806-7800basic-tips-tricks-and-examples/#findComment-4644743 Share on other sites More sharing options...
Recommended Posts
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.