Click here to Skip to main content
12,069,812 members (49,950 online)
Click here to Skip to main content
Add your own
alternative version

Tagged as


9 bookmarked

A Simple Racing Cars (Tokens) Game App

, 30 Sep 2013 CPOL
Rate this:
Please Sign up or sign in to vote.
Using Thread and Java Swing components


Based on an assignment 'Racing Tokens', instead of using a Timer, I used Thread to race tokens (cars) around rounded rectangular tracks. Each token runs on its own thread. Each token can be any appropriate Java Swing shape (circle, triangle, or square).

Syntax to run: java Program [laps, tokens]

With laps (range from 1 to 3) and tokens (range from 2 to 4) are optional. Default 1 lap and 4 token. Tracks are dynamic sizing.

The plan of attack

Implement MVC model, I came up with three packages:

  • model: includes these classes: Token, Race, and RaceBuilder
  • view: includes these classes: RaceFrame, RacePanel, and ControlPanel
  • controller: includes RaceRunnable class

The class is the entry to run the program.

The details 

Token class

Start with class. It contains all the data associated with an actual token: name, radius (for a circle), color, position coordinates X and Y, distance and distance-right (down, left, up) it has run, track width and height, velocity,...

Velocity (pixels per second) is randomly calculated.

Among the setter and getter methods, the most essential ones are the methods to move (right, down, left, and up) associated with the draw methods based on its position.

public void moveToken() {
if (this.distanceRight <= this.trackWidth) {
    // move right, if this token has reached to far right, then move down
    this.shouldMoveRight = true;

} else if (this.distanceDown <= this.trackHeight) {
    // move down, if this token has reached the bottom, then move left
    this.shouldMoveDown = true;

} else if (this.distanceLeft <= this.trackWidth) {
        // code
} else if (this.distanceUp <= this.trackHeight) {
    // code


The method for the token to move it to the left is:

private void moveLeft(int miliseconds) {
    double pixels = 0.001D * velocity * miliseconds;
    this.distanceLeft += pixels;
    this.distance += pixels;

    this.distanceUp = 0;

and at the same time, draw its circle:

private void drawLeft(Graphics g) {
            this.initialPosition.x + (int) Math.round(this.distanceRight)
                    - (int) Math.round(this.distanceLeft),
            this.initialPosition.y + (int) Math.round(this.distanceDown),
            DIAMETER, DIAMETER);

(*) One important note of this Token class is that it implements the Runnable interface. So it is a task to be run in a thread.

Race class 

To store a list of Tokens, along with how many laps to run, the total distance to run for each token. The two key methods here is: (1) determine if all tokens are still running:

public boolean areAllTokensRunning() {
    for (Token token : tokens) {
        if ((this.distance + Token.RADIUS) > token.getDistance()) {
            return true;

    return false;

and (2) determines the winner:

public Token isWinner() {
    for (Token token : tokens) {
        if (this.distance <= token.getDistance()) {
            return token;

    return null;

The GUI classes

The main frame class, RaceFrame is to be the main container to display the app. It includes the RacePanel and ControlPanel GUI.

The RacePanel is to hold the Race (which contains a numbers of Tokens) and rounded rectangle tracks. Its size (width and height) determine the distance to run.

The ControlPanel includes the buttons (Start/Stop/Resume, increase/decrease speed), the label to declare the winner. These buttons listen to the user's activities and act accordingly.

The Controller

The RaceRunnable class, just needs to pass the parameters and fire the token's run() method to start thread for each token, through a 'chain of command' RaceFrame, RacePanel, and RacetoToken.

RaceRunnable itself is a task and to be run in the event dispatch thread:

public void run() {
    while (raceRunning && race.areAllTokensRunning()) {
        int track = 2 * (racePanel.getWidth() + racePanel.getHeight());
        race.setDistance(track * race.getLaps() - 480);

        race.updateTokenPositions(1, racePanel.getWidth() - 120,
                racePanel.getHeight() - 120); 
                  // 120 pixels margin from the right and top border

        SwingUtilities.invokeLater(new Runnable() {
            public void run() {

                if (race.isWinner() != null) {
                    raceRunning = false;

        try {
        } catch (InterruptedException e) {


  • This program needs a better way to choose the 'right' time to turn 'curly' at the track corner.
  • Also, it has not set up a 'fair game' and determined 'reasonably' which token wins.
  • The move and draw token methods are lengthy and should be re-written.
  • ...


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Lộc Nguyễn
Software Developer
United States United States
currentJob = new ComputerScientist("ND-1550", "02/04", "SPAWAR SSC PAC");

while (live) {
try {
} catch (Exception ex) {

You may also be interested in...

Comments and Discussions

QuestionWhat is the main purpose of article? Pin
Nghia Do30-Sep-13 13:52
memberNghia Do30-Sep-13 13:52 
AnswerRe: What is the main purpose of article? Pin
Lộc Nguyễn30-Sep-13 15:18
memberLộc Nguyễn30-Sep-13 15:18 
This is a program to race the tokens (cars) around a rounded rectangular track. You can set how many laps and how many tokens to start running. You can increase or decrease random velocity (pixels/ms) also.

There are different ways to solve this problem. You can either use the Timer to trigger the time event, or use thread (which I chose) for this. Also, I implement the idea of MVC (Model - View - Control) to separate the data/logic and GUI components. As a result, the process of developing and maintaining will be less complicated. Later on, you can continue to add more functionality, such as a clock, draw a car instead of a simple circle, or adding sounds,...

Lộc N

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.160208.1 | Last Updated 30 Sep 2013
Article Copyright 2013 by Lộc Nguyễn
Everything else Copyright © CodeProject, 1999-2016
Layout: fixed | fluid