Creating an old school amiga demo bitmap scroll in Python 3 and pygame 2

 Back in the old days (1980:s) I did some demo coding on first the commodore 64 and later on an Amiga 500. I wouldn't say I was very good at it but I did manage to make some simple demos

One feature that was a "must have" in all Amiga demos was a "sprite scroller". A sprite scroller displays a moving, e g scrolling, text on the screen. But not with the standard font, it must have a special and very cool looking font which was often made in a paint program like Deluxe paint. The bitmap image was then cropped to the characters and displayed in the scroll.

Now, when I try to make my kids interested in coding, I was talking to them about text scrolls. It ended up with me trying to create a "sprite scroller" in Python.

Here is a screenshot of the result



If I recall correctly the way it was done on an Amiga was that I (or a friend) created a font bitmap containing all the characters needed for displaying the text message. The bitmap was then cropped into the different sprites and stored in memory.

So how can this be done in Pyhton? I will be using pygame but you can do this with pyglet as well.

First, we need to get a cool font bitmap. I found "Bitmap fonts" from Ian Hanschen: https://github.com/ianhan/BitmapFonts and I borrowed a few from him.

Now that we have our bitmap font I will create a class for the scroller.


#Class for sprite scroller
class sprite_scroll:
    def __init__(self, filename, text, y_pos, start_pos, char_width, char_height, chars_line, charmap, speed=3):
        self.text = text #Scroll text
        self.speed = speed #speed of the scroll
        self.y_pos = y_pos #y position of the scroll
        self.x_pos = start_pos  #Start x position of the scroll
        self.char_map = charmap #the order of the characters in the bitmap
        self.CHAR_W = char_width #width of the char in the bitmap
        self.CHAR_H = char_height #height of the char in the bitmap
        self.ROWS_PER_LINE = chars_line #number of chars per line in the bitmap
        self.font_image = pygame.image.load(filename).convert() 
        self.font_image.set_colorkey((0,0,0))  # Black will not be blit.
        self.chars = {}

        #Crop font image and store all chars in an array
        for i in range(len(self.char_map)):
            #Crop 3chars one by one from the font image
            row=int(i/self.ROWS_PER_LINE)
            col=int(i-(self.ROWS_PER_LINE*row))
            cropx,cropy = self.CHAR_W*col,self.CHAR_H*row
            cropped_region = (cropx, cropy, self.CHAR_W,self.CHAR_H)
            #Add cropped char to chars array
            self.chars[i]=self.font_image.subsurface(cropped_region)
   
    #Draw the scroll
    def draw(self):      
        w=0
        for character in self.text:
            w+=self.CHAR_W
            #Find the position of the char in the array
            index=self.char_map.find(character)
            #Draw it to the screen buffer
            canvas.blit(self.chars[index], (self.y_pos+w,self.x_pos))
        
        #Set scroll position
        if self.y_pos+(len(self.text)*self.CHAR_W)<0:
            self.y_pos=SCREEN_W    
        self.y_pos-=self.speed 


Then it is only a matter of instanciating the scroller with the input parameters. The size of the chars in the bitmap and the order (charmap) is sometimes tricky to get right. If the bitmap only contains upper case letters then the text must also be upper case and vice versa.

Import pygame (install it with pip if you haven't already), create you program and add this to the progam. 


    scrolltext="  A very long scroll text. Lorem ipsum dolor sit amet consectetur adipiscing elit. Ut urna tellus varius eget nisl tristique ultrices mattis leo. Cras iaculis purus non posuere volutpat velit massa hendrerit felis eu dictum nisi enim a orci. Ut quis tincidunt nisl. Nulla aliquam euismod velit in interdum.  ".upper()
    scroll_text=sprite_scroll("bennyfnt.png",scrolltext,SCREEN_W,SCREEN_H-100,32,32,10," !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZÖ",4)
    scroll_text2=sprite_scroll("carebearr.png","   A REALLY FAST SCROLL TEXT!!!!      ",SCREEN_W,100,26,26,12," !\"_´@$'()*+#-.:0123456789abcdefgABCDEFGHIJKLMNOPQRSTUVWXYZ",12)
    scroll_text3=sprite_scroll("mdethfnt.png","  AND A REALLY SLOW SCROLL TEXT AS WELL!!!!!      ",SCREEN_W,SCREEN_H/2,32,32,10," !\"ÅÄÖ#'()$+,-._0123456789:;<=>?%ABCDEFGHIJKLMNOPQRSTUVWXYZ",1)

In your pygame main loop add a call to the scroller's draw method


    #main loop
    while run:       
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run=False
            elif event.type == pygame.KEYDOWN:
                run = False

        #Clear screen
        canvas.fill((0,0,0))

        scroll_text.draw()
        scroll_text2.draw()
        scroll_text3.draw()
        
        #Flip updates the whole screen
        pygame.display.flip()

        #Set FPS=60
        clock.tick(60)
        

Comments

Popular posts from this blog

MS SQL server: CTE example

Powershell: import complex PRICAT csv file