Scoreboards and Video Routing in Python
Time and Possession
The clock is a unique case because it is the only game variable that updates independently. Everything else is a response to something that happens on the court.
In the clock function (lines 314-331), getClock
returns a string that represents the current game time, called by a recurring interval in a JavaScript function on the operator's web page to update the operator's clock. A timer event in the graphics thread both updates the internal clock variable and redraws the clock on the scoreboard display.
updateClock
is only found in the JavaScript and does the job of keeping the control page clock up to date. It calls getClock
by jQuery to get the current clock time then updates the HTML div
with the current value:
function updateClock() {{ $.post ( "getClock" , function ( data ) {{ $ ( "#clock" ).html ( data ); }} ); }}
Both the clockRun
and clockStop
functions change the state of self.scoreboard.clk.running
. If that variable is True
, the clock is updated. If it's False
, the clock is not updated or is, for all practical applications, paused. clockStop
also calls self.gameEvent
to add an entry that the clock was stopped. Because the clock is not team-specific, the second argument is
. The JavaScript version of these functions (lines 80-92) are not shown. Once the Python function is called by jQuery, a JavaScript interval is either set or cleared to update the control page.
For the clockSet
function, the variable self.scoreboard.clk.seconds
keeps track of the game time remaining in seconds, which is set to one second more than requested. Next, self.scoreboard.clk.tick
automatically subtracts one second. Passing manual = True
forces a redraw of the clock even though it is not running. Finally, self.scoreboard.clk.clockString
, which is a text representation of the time remaining in minutes and seconds, returns.
The JavaScript version can be found on lines 101-116 (not shown). It asks the operator what the clock should be set to and will contain either the requested time or null
if the dialog box was canceled.
If the value is valid, the request is split into minutes and seconds and then converted to seconds. After a new object is created and a seconds
parameter added, it is posted by jQuery back to the Python function. The control screen then updates with the new clock value and the update interval clears so clock requests are not made until it starts running again.
The posession
[sic] function (333-339) calls the toggle
method of self.scoreboard.posession
, which flips which team currently has the ball (indicated by the <
and >
symbols as arrows).
Lines 336 and 337 check to see which team has possession and add a gameEvent
to reflect the change. Finally, two strings are returned separated by a colon; each string is either a space or one of the <
or >
symbols. The JavaScript version is on lines 71-78 (not shown). After posting a possession change by jQuery the return string is split into two parts, and the left and right divs are updated on the control screen.
The Clock Class
The clock
class (lines 341-371) manages the game clock for the main graphics (scoreboard) display. The __init__
function sets up a few things: self.screen
is a reference to the screen object passed when creating the class; self.width
stores the screen width by calling get_width()
on the screen surface; self.height
is set explicitly to define how tall you want the clock to be displayed; and self.seconds
is the time on the clock, initialized to 6 * 60
seconds to reflect six-minute periods. Line 347 creates a Pygame surface onto which the clock is drawn, and line 348 sets up the font. Finally self.running
tracks whether the clock is running or paused.
Lines 351-354 calculate the clock values and convert to int
; seconds
is the mod (remainder) of self.seconds / 60
. Finally, self.clockString
is assembled from the calculated values.
The main loop calls the tick
function (lines 356-363) once a second. If time is left on the clock and either self.running
or manual
is set to True
, self.seconds
decrements by one, and the same calculations as before are repeated to update self.clockString
. The manual
parameter used when setting the clock forces the clock to be regenerated immediately rather than waiting for the next automatic call to tick
.
The render
function (lines 365-371) draws the clock. self.clockFont.render
takes self.clockString
and a color tuple as arguments. The True
argument says to anti-alias the text as it is drawn. The result is timeSurf
, a Pygame surface with the current game time drawn onto it.
After the center point of timeSurf
is calculated, self.clockSurf
is cleared by filling it with black and blitting (copying) timeSurf
onto it. Then the surface is returned. This copying might seem like an extra step, but here's what's happening: When self.clockFont.render
generates the text, the surface is the exact size of the text it generated. For it to fill the space at the dimensions specified in __init__
, you have to copy it onto the larger surface.
The Posession Class
The posession
class (lines 373-406) indicates who has the ball at any given time. __init__ ( self )
sets up the graphical display, with the initial state specified by self.direction
(who currently has the ball). A surface is created and initialized with self.leftString
and self.rightString
.
The convenience function makeSurfaces
creates self.leftSurf
and self.rightSurf
possession arrows rendered with <
and >
symbols.
When the toggle
function (lines 388-396) is called, possession has changed from one team to the other. The if
checks to see which team currently has possession and then updates all of the variables to their opposite states. Note that self.leftString
and self.rightString
either have an arrow or an empty string.
When everything is ready to be drawn in the render
function, self.posSurf
is cleared by filling it with black (line 399) before generating the label text, calculating the center point, and blitting it onto the final surface.
Lines 404 and 405 make sure the arrow is blitted on the appropriate side of the surface. If self.direction
is <
, the arrow is drawn on the left side of the surface; otherwise, it's drawn on the right before the final surface is returned.
Buy this article as PDF
(incl. VAT)
Buy Linux Magazine
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Subscribe to our ADMIN Newsletters
Support Our Work
Linux Magazine content is made possible with support from readers like you. Please consider contributing when you’ve found an article to be beneficial.
News
-
Halcyon Creates Anti-Ransomware Protection for Linux
As more Linux systems are targeted by ransomware, Halcyon is stepping up its protection.
-
Valve and Arch Linux Announce Collaboration
Valve and Arch have come together for two projects that will have a serious impact on the Linux distribution.
-
Hacker Successfully Runs Linux on a CPU from the Early ‘70s
From the office of "Look what I can do," Dmitry Grinberg was able to get Linux running on a processor that was created in 1971.
-
OSI and LPI Form Strategic Alliance
With a goal of strengthening Linux and open source communities, this new alliance aims to nurture the growth of more highly skilled professionals.
-
Fedora 41 Beta Available with Some Interesting Additions
If you're a Fedora fan, you'll be excited to hear the beta version of the latest release is now available for testing and includes plenty of updates.
-
AlmaLinux Unveils New Hardware Certification Process
The AlmaLinux Hardware Certification Program run by the Certification Special Interest Group (SIG) aims to ensure seamless compatibility between AlmaLinux and a wide range of hardware configurations.
-
Wind River Introduces eLxr Pro Linux Solution
eLxr Pro offers an end-to-end Linux solution backed by expert commercial support.
-
Juno Tab 3 Launches with Ubuntu 24.04
Anyone looking for a full-blown Linux tablet need look no further. Juno has released the Tab 3.
-
New KDE Slimbook Plasma Available for Preorder
Powered by an AMD Ryzen CPU, the latest KDE Slimbook laptop is powerful enough for local AI tasks.
-
Rhino Linux Announces Latest "Quick Update"
If you prefer your Linux distribution to be of the rolling type, Rhino Linux delivers a beautiful and reliable experience.