Lars Cornelissen


Exploring AST in Python Programming and Creating a Python-Controlled Robot Game in JavaScript

Profile Picture Lars Cornelissen
Lars Cornelissen • Follow
CEO at Datastudy.nl, Data Engineer at Alliander N.V.

4 min read


black and white round logo

Understanding AST in Python

Understanding AST in Python

Have you ever wondered how Python understands the code you feed it? Well, it breaks down your code into something called an Abstract Syntax Tree (AST). This might sound complicated, but trust me, it's a fascinating part of how programming languages work.

What is an AST?

In simple terms, an AST is a tree representation of the structure of your source code. Each node in the tree denotes a construct occurring in the source code. These constructs can be variables, operators, functions, or any control flow elements. Think of it as a hierarchical blueprint of your code, helping compilers or interpreters understand and process it.

Why is AST Important?

Alright, so why should we care about ASTs? Here’s why:

Now, let's keep things practical. We'll walk through some Python code snippets to see how we can generate and manipulate an AST using Python's 'ast' module.

Generating an AST

First things first, let's generate an AST from a simple piece of Python code. Consider this code snippet:

import ast

code = """
def say_hello():
    print('Hello, world!')
"""

# Parse code into an AST
parsed_code = ast.parse(code)
print(ast.dump(parsed_code, indent=4))

In this snippet, we use ast.parse to parse a string of Python code into an AST, and then we print the tree structure using ast.dump.

Manipulating an AST

Next, let's try manipulating this AST. Say we want to change the function name from say_hello to greet.

class RenameFunction(ast.NodeTransformer):
    def visit_FunctionDef(self, node):
        if node.name == 'say_hello':
            node.name = 'greet'
        self.generic_visit(node)
        return node

transformer = RenameFunction()
modified_tree = transformer.visit(parsed_code)

# Print the modified AST
print(ast.dump(modified_tree, indent=4))

Here we define a class RenameFunction that inherits from ast.NodeTransformer. We override the visit_FunctionDef method to rename the function, and then we apply this transformation to our original tree.

Why use AST in Python?

The 'ast' module in Python is immensely powerful for developers who are interested in deep code analysis and transformations. Let’s summarize the key functions:

Function Purpose
ast.parse Converts source code into an AST
ast.dump Returns a stringified version of the AST
ast.NodeTransformer ALlows for transformation of nodes in the AST
ast.NodeVisitor Visits nodes in the AST for analysis

Using these functions, you can analyze, modify, and generate code proactively, opening up a windfall of possibilities!

Remember, every great tree starts with a seed, or in this case, some lines of code. 🌱

Building a JavaScript Game Framework

Building a JavaScript Game Framework

Game development has always been an exciting and challenging field. Whether you're an experienced developer or a newbie, creating your own game framework can be a rewarding experience. Let's roll up our sleeves and build a basic game framework in JavaScript using a popular library: Phaser.js.

Choosing Your Tools

To start off, you'll need some essential tools and libraries. Here's a list of the basics:

Now, let's dive into the setup process.

Setting Up Phaser.js

First things first, you need to get Phaser.js up and running. Here's a quick way to set it up:

  1. Download Phaser.js: You can download Phaser from its official website. Save it to your project directory.
  2. Project Structure: Create a folder for your project and structure it like this:
my-phaser-game/
    ├── index.html
    ├── js/
    │   └── phaser.min.js
    └── assets/

Your index.html will look something like this:

<!DOCTYPE html>
<html>
<head>
    <title>My Phaser Game</title>
    <script src="js/phaser.min.js"></script>
</head>
<body>
    <script src="js/game.js"></script>
</body>
</html>

Next, create a game.js file under the js/ directory.

Creating the Game Loop

The game loop is the heart of any game. It updates the game state and renders the game scene at a fixed frequency. Let’s get our initial game loop up and running in game.js.

window.onload = function() {
    const config = {
        type: Phaser.AUTO,
        width: 800,
        height: 600,
        scene: {
            preload: preload,
            create: create,
            update: update
        }
    };

    const game = new Phaser.Game(config);

    function preload() {
        // Load assets here
    }

    function create() {
        // Initialize game objects here
    }

    function update() {
        // Game loop logic goes here
    }
};

Here’s a breakdown of the scene lifecycle functions:

Adding a Simple Game Object

Let's add a simple sprite to your game. First, you'll need an image. Save an image (e.g., player.png) in your assets/ folder.

Update your preload and create functions as follows:

function preload() {
    this.load.image('player', 'assets/player.png');
}

function create() {
    this.player = this.add.sprite(400, 300, 'player');
}

Now, when you run your game, you should see the player sprite in the middle of the screen.

Running Your Game

If you are using Node.js, you can set up a simple server to view your game in the browser. Use a package like http-server for this. Run the following command in your project directory:

npm install -g http-server
http-server

Open your browser and navigate to http://localhost:8080 to see your game in action.

And there you have it—a basic game framework in JavaScript using Phaser.js! Of course, this is just the beginning. You can build upon this by adding more game objects, interactivity, and game mechanics. 🎮

Integrating Python to Control a Robot in the Game

Now that we have our basic game framework using Phaser.js, let's take things up a notch by integrating Python to control a robot within our JavaScript game. This combination of Python and JavaScript opens the door to some really cool possibilities, such as using Python's robust libraries for AI or sensor data processing to control game elements in real-time. That sounds like a lot of fun, right? Let's get started!

Choosing a Communication Protocol

To connect Python with our JavaScript game, we'll use WebSockets—a powerful protocol that allows for real-time bi-directional communication over a single TCP connection. The idea is to have a WebSocket server set up in Python and connect to it client-side from our JavaScript game.

Setting Up a WebSocket Server in Python

First, let's set up a WebSocket server using Python. We'll use the websockets package for this purpose. If you haven't installed it yet, you can do so using pip:

pip install websockets

Now, let's write a simple WebSocket server that sends control commands to our game:

import asyncio
import websockets

async def control_robot(websocket, path):
    while True:
        # Wait for a command to be sent from the client
        command = await websocket.recv()
        print(f"Received command: {command}")

        # Simulate command processing and send a response
        response = f"Command {command} executed"
        await websocket.send(response)

start_server = websockets.serve(control_robot, "localhost", 8765)

# Run the WebSocket server
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()

This code sets up a basic WebSocket server that listens for messages and sends back a confirmation response. You can run this code in your terminal to start the server.

Connecting JavaScript to the WebSocket

Now that our WebSocket server is running, let's connect our Phaser.js game to this server. We'll modify our create function in game.js to establish a WebSocket connection:

function create() {
    this.player = this.add.sprite(400, 300, 'player');

    // Create WebSocket connection
    const socket = new WebSocket('ws://localhost:8765');

    // Connection opened
    socket.addEventListener('open', function (event) {
        socket.send('Hello Server!');
    });

    // Listen for messages
    socket.addEventListener('message', function (event) {
        console.log('Message from server ', event.data);
    });
}

With this code, your game will establish a WebSocket connection and send a 'Hello Server!' message upon connection. The server's response will be logged in the browser's console.

Sending Control Commands

Next, let’s write some functions to send control commands to our Python server. For simplicity, let's create functions to send movement commands (e.g., move_up, move_down, move_left, move_right). We can trigger these functions using keyboard events.

function create() {
    this.player = this.add.sprite(400, 300, 'player');

    const socket = new WebSocket('ws://localhost:8765');
    socket.addEventListener('open', function (event) {
        socket.send('Hello Server!');
    });

    socket.addEventListener('message', function (event) {
        console.log('Message from server ', event.data);
    });

    this.input.keyboard.on('keydown', function (event) {
        switch(event.key) {
            case 'ArrowUp':
                socket.send('move_up');
                break;
            case 'ArrowDown':
                socket.send('move_down');
                break;
            case 'ArrowLeft':
                socket.send('move_left');
                break;
            case 'ArrowRight':
                socket.send('move_right');
                break;
        }
    });
}

This code will send movement commands to the WebSocket server whenever the arrow keys are pressed. The server will log these commands and send a response back to the game.

Showcasing a Working Demo

So far, we have set up a WebSocket server in Python and a WebSocket client in JavaScript. Let's test everything out to see if we can control the robot. Make sure your WebSocket server is running, then open your game in a web browser. Press the arrow keys and check the terminal where the server is running to see the received commands. If everything is working, you should see log messages corresponding to each arrow key press.

Command Description
move_up Moves the robot up
move_down Moves the robot down
move_left Moves the robot to the left
move_right Moves the robot to the right

Not only have we integrated Python with our JavaScript game, but we have also enabled real-time control of game elements using WebSocket communication! This is just the beginning. You can extend this setup with more complex AI algorithms, sensor data, or even machine learning models running in Python to control various aspects of your game. 🚀


Python

JavaScript

AST

robot game

programming

game development