Skip to content
Home » Kivy Part 20 – Slugrace – Race Screen GUI

Kivy Part 20 – Slugrace – Race Screen GUI

Spread the love

In one of the previous parts we created a basic Race Screen GUI. This is the screen where we’re going to spend most of the time during the game.

But before we delve into the topic, here’s some info for you.

*****

Book Info

I just published my Kivy book, GUI Programming with Python and Kivy. It’s pretty long (over 800 pages) and comprehensive. And, which also counts, easy to read. The book contains lots of illustrations.

This book covers all the basics that you need to know to start programming GUI applications with Python and Kivy. Throughout the book we are building a GUI application from scratch, a fully functional game using all kinds of tools that Kivy has to offer. It’s our Slugrace project, but covered in a much more in-depth manner.

Each part of the book starts with a theoretical introduction of a topic or idea that we then implement in the project. I assume you have no prior knowledge of the Kivy library, but you should have at least some basic knowledge of the Python programming language, including the object-oriented programming paradigm as this is what we will be using a lot in this book.

Kivy book

The book covers all the basic elements of Kivy that you have to know, like widgets, layouts, Kivy ids and properties, graphics, screens, animation, sound. Finally we’ll deploy the app to Windows. It is pretty comprehensive and after you finish it, I’m sure you’ll be able to create your own awesome GUI apps of any kind, not just games.

I hope you will have at least as much fun reading the book as I had writing it.

As far as this Kivy series is concerned, the following parts will contain the most important elements covered in the book. However, some elements will be presented in a simplified way here on my blog or omitted completely.

____________

If you are interested, you can purchase the book in four versions. Here are the links:

1) ebook – pdf version on my website – in full color

Here you can see the description of the book, sample graphics from the book and the full table of contents.

2) ebook – Kindle version on Amazon – in full color

3) paperback version on Amazon – in black and white

4) paperback version on Amazon – in full color

*****

And Now Let’s Move On…

So, what do we have now? Here’s the Python code in the race.py file:

# File name: race.py

import kivy
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout

class RaceApp(App):
    def build(self):
        return BoxLayout()

if __name__ == '__main__':
    RaceApp().run()

And here’s the kv file:

# File name: race.kv

<BoxLayout>:
    orientation: 'vertical'
    
    ### INFO, STATS AND BUTTONS ###
    Label:
        text: 'Info, Stats and Buttons'
    
    ### THE TRACK ###
    Label:
        text: 'The Track'
    
    ### THE BETS ###
    Label:
        text: 'The Bets'

As you can see, it’s very basic. Actually you can only see the three main areas:

1) Info, Stats and Buttons

2) The Track

3) The Bets

If you run this program, you will see this:

race screen - current stage

The Final Version of the Race Screen

OK, so this is what we have. And what are we aiming at? Well, the final version of the Race screen should look something like this:

race screen - final version with bets

What we have and what we’re aiming at are not very much alike. This means there’s a lot of work to do. Actually it means much more work than we can do in one part, so here we’re only going to start. But before we start, just one remark. In the final version image you can see the Bets area near the bottom. In the final version this part will be a separate screen which will be inserted here and will be replaced with the Results screen when each race is finished. So after one slug crosses the finish line, the Race screen will look like this:

race screen - final version with results

As you can see, now the lower part is different. For now, however, we’re going to put a placeholder here and implement the Bets and Results screens as separate apps in the following parts of this series, just as we’re doing now with all the screens. This is because we can run each of them separately and see how it looks. When we learn how to make all the Python and kv files communicate, we’ll change this behavior so that there will be just one main app and the screens will be swapped as needed.

And one more thing. We want all the screens to look consistent, so we’re going to use the same styles for labels, buttons and other widgets. That’s why we’re going to use the custom widgets we defined in the class rules when we were creating the Settings screen. At this point we’ll just copy them and put above the root widget just like we did before, but this naturally means repetitive code again. It would be much better to define all the custom widgets in one place and then use them across the whole application, and this is what we actually are going to do, but not now. Before we must learn how files communicate in Kivy. So, don’t worry about the repetitive code for now, it will change.

Your Panda3D Magazine

Make Awesome Games and Other 3D Apps

with Panda3D and Blender using Python.

Cool stuff, easy to follow articles.

Get the magazine here (PDF).

The root Widget of the Race Screen

With that said, let’s choose a root widget. As you remember, we used a BoxLayout in the Settings screen. We’re going to use a BoxLayout in the Race screen too, at least for now. So, let’s modify the Python file:

# File name: race.py

import kivy
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout

class RaceScreen(BoxLayout):
    pass

class RaceApp(App):
    def build(self):
        return RaceScreen()

if __name__ == '__main__':
    RaceApp().run()

And now kv file:

# File name: race.kv

<RaceScreen>:
    orientation: 'vertical'
    
    ### INFO, STATS AND BUTTONS ###
    Label:
        text: 'Info, Stats and Buttons'
    
    ### THE TRACK ###
    Label:
        text: 'The Track'
    
    ### THE BETS ###
    Label:
        text: 'The Bets'

Python Jumpstart Course

Learn the basics of Python, including OOP.

with lots of exercises, easy to follow

The course is available on Udemy.

An Overview of the Areas of the Race Screen

At this point we just used RaceScreen as the root widget, which is a subclass of BoxLayout. And now let’s have a look at all the areas one by one. How are we going to implement them?

The Info, Stats and Buttons Area Overview

Well, first comes the Info, Stats and Buttons area. This is how it should eventually look:

The Info, Stats and Buttons Area Overview

We’ll implement it as a GridLayout with four columns. There will be one subarea in each column:

– in column 1: the Game Info subarea implemented as a BoxLayout

– in column 2: the Slugs’ Stats subarea implemented as a BoxLayout

– in column 3: the Players’ Stats subarea implemented as a BoxLayout

– in column 4: the Buttons subarea implemented as a BoxLayout

The Track Area Overview

Then there’s the Track area, so the part of the window where we’ll watch the slugs competing with one another. This is what it should look like before a race starts:

The Track Area Overview - before race

and after a race finishes:

The Track Area Overview - after race

This area will be implemented as a horizontal BoxLayout with two subareas:

– the track subarea implemented as a RelativeLayout

– the winner subarea implemented as a BoxLayout

For now we’re just going to use some placeholders without the images. We will add the graphics when we learn how to do it, which is going to be soon.

The Bets Area Overview

Finally we have the Bets area, or, to be more precise, the Bets/Results area, because here the two screens, Bets and Results, will be swapped after each race. So, this is how it should look before a race:

Bets area with Bets

and after a race:

Bets area with Results

Here you can see how it should look if there are two players, but the number of players may be up to four. As you remember, this is one of the things that you can set in the Settings screen.

We’re not going to implement this area at all for now, because we’ll implement the Bets and Results screen separately and then only inject them here. For the time being we’ll use just a placeholder for the whole area.

So, now that you know what we want to achieve, let’s give it a try.

The Areas One by One

The only area that we are going to implement relatively completely here is the Info, Stats and Buttons area. Let’s do it.

Blender Jumpstart Course

Learn the basics of 3D modeling in Blender.

step-by-step, easy to follow, visually rich

The course is available on Udemy and on Skillshare.

The Info, Stats and Buttons Area Implementation

So, we need a GridLayout with four columns and a BoxLayout in each column. In the kv file I added some of the properties that I discussed before like size_hint, padding and spacing. If you don’t remember how to use them, just refer to those parts. I also added the class rules with the custom widgets that we need. There is also one new custom widget, the BoldLabel. Here’s the kv file:

# File name: race.kv

### CLASS RULES ###

<RegularLabel@Label>:
    text_size: self.size
    halign: 'left'
    valign: 'center'

<BoldLabel@RegularLabel>:    
    bold: True

<RaceScreen>:
    orientation: 'vertical'
    
    ### INFO, STATS AND BUTTONS ###
    GridLayout:
        cols: 4
        size_hint: 1, .5
        spacing: 4

        # Game Info
        BoxLayout:
            orientation: 'vertical'
            padding: 10

            BoldLabel:
                text: 'Game Info:'
            BoxLayout:                    
                RegularLabel:
                    size_hint: (2.5, 1)
                    text: 'Race No'
                RegularLabel: 
                    text: '1'            
            BoxLayout:                                                      
                RegularLabel: 
                    size_hint: (2.5, 1)                        
                    text: 'Number of races set:' 
                RegularLabel:
                    text: '10'                        
            BoxLayout:
                RegularLabel: 
                    size_hint: (2.5, 1)
                    text: 'Races finished:' 
                RegularLabel:
                    text: '0'          
            BoxLayout:
                RegularLabel:
                    size_hint: (2.5, 1)
                    text: 'Races to go:' 
                RegularLabel:
                    text: '10'

        # Slugs' Stats           
        BoxLayout:
            orientation: 'vertical'
            padding: 10

            BoldLabel:
                text: "Slugs' Stats"
            
            BoxLayout:
                spacing: 10
                RegularLabel:
                    text: "Speedster"
                RegularLabel:
                    text: '7 wins'
                RegularLabel:   
                    text: '70%'
                    
            BoxLayout:
                spacing: 10
                RegularLabel:
                    text: "Trusty"
                RegularLabel:
                    text: '1 win'
                RegularLabel:   
                    text: '10%'
            
            BoxLayout:
                spacing: 10
                RegularLabel:
                    text: "Iffy"
                RegularLabel:
                    text: '0 wins'
                RegularLabel:   
                    text: '0%'
            
            BoxLayout:
                spacing: 10
                RegularLabel:
                    text: "Slowpoke"
                RegularLabel:
                    text: '2 wins'
                RegularLabel:   
                    text: '20%'

        # Players' Stats           
        BoxLayout:
            orientation: 'vertical'
            padding: 10

            BoldLabel:
                text: "Players' Stats"                                

            BoxLayout:                                     
                RegularLabel:
                    text: 'Player 1'
                RegularLabel:
                    text: 'has $1000' 

            BoxLayout:  
                RegularLabel:
                    text: 'Player 2'
                RegularLabel:
                    text: 'has $800'

            BoxLayout: 
                RegularLabel:
                    text: 'Player 3'
                RegularLabel:
                    text: 'has $1300'

            BoxLayout:  
                RegularLabel:
                    text: 'Player 4'
                RegularLabel:
                    text: 'has $1200'

        # Buttons
        BoxLayout:
            orientation: 'vertical'   
            spacing: 3 
      padding: 10
            size_hint: .7, 1               
            
            Button:
                text: 'End Game'  
                font_size: 18
                size_hint: (None, None)
                size: 200, 40
                pos_hint: {'right': 1} 

            Button:
                text: 'Instructions'   
                font_size: 18
                size_hint: (None, None)
                size: 200, 40
                pos_hint: {'right': 1} 
            
            Button: 
                text: 'Sound'
                font_size: 18
                size_hint: (None, None)
                size: 200, 40
                pos_hint: {'right': 1} 
                
               
    
    ### THE TRACK ###
    Label:
        text: 'The Track'
    
    ### THE BETS ###
    Label:
        text: 'The Bets'

Well, this code is pretty lengthy, but also pretty straightforward. There’s nothing new in it. If you now run the app (from the race.py file), the widgets will partially overlap, which doesn’t look good, but remember that in the final version the app window will be bigger. At this moment you can just manually resize the window horizontally and vertically and then you will see this:

The Info, Stats and Buttons Area Implementation

Looks a bit more like the final version, right? Anyway, don’t pay attention to the numeric values in the code and image above, like the number of wins, race number, etc. I just put some arbitrary values here which doesn’t make sense at all, but at least you can see how it’s going to look. These values will be then handled programmatically.

The Track Area Implementation

The Track area will take shape only when we add the images to it, but for now let’s add some dummy data so that there is at least something. This area will be implemented as a horizontal BoxLayout with two subareas: one for the track and one for the image of the winner along with some info about the winning slug. Here’s the kv code for this area:

# File name: race.kv

### CLASS RULES ###

...

<RaceScreen>:
    ...
    ### INFO, STATS AND BUTTONS ###
    ...
    
    ### THE TRACK ###
    BoxLayout:        
        padding: 10

        # track
        Label:            
            text: 'TRACK'

        # winner
        BoxLayout:
            orientation: 'vertical'
            size_hint: (.18, 1)

            Label:
                text: "The winner is"
                font_size: 24
                size_hint: 1, .2
                bold: True

            Label:
                text: "Trusty"
                font_size: 32
                size_hint: 1, .2
                bold: True

            Label:
                text: 'WINNER'


        
    
    ### THE BETS ###
    ...

Run the code again and resize the window. You should now get something like this:

The Track Area Implementation

Although still very incomplete, this will have to do for now. I’m not going to touch the Bets area here because we’ll build the Bets screen from scratch in the next part.


Spread the love

Leave a Reply