Modules and Imports

A module is a Python file containing functions, classes, and variables. When a project grows beyond one file, code is split into modules so each file has a focused responsibility. You bring code from another module into the current file using import.

Basic Import

import math

distance = math.sqrt(dx**2 + dy**2)

After import math you access its contents with the math. prefix (called dot notation). The module object contains all the functions and variables defined in math:

>>> import math
>>> print(math)
<module 'math' (built-in)>
>>> math.pi
3.141592653589793
>>> math.sqrt(2)
1.4142135623730951

From Import

To bring specific names directly into the current namespace, use from … import:

from math import sqrt, pi, sin, cos

distance  = sqrt(dx**2 + dy**2)   # no 'math.' prefix needed
angle_rad = degrees * (pi / 180.0)
x_offset  = sin(angle_rad) * radius

You can also rename with as:

import numpy as np

positions = np.array([[0, 0, 0], [1, 2, 3]])

Importing from Packages

A package is a directory of modules. Acron’s Python API is organised into packages. The first line of every Acron program uses a package import:

from direct.showbase.ShowBase import ShowBase

Breaking that down:

  • direct — the top-level Acron Python package

  • showbase — a sub-package (subdirectory) inside direct

  • ShowBase — the module file ShowBase.py

  • import ShowBase — the class defined inside that module

The dotted path mirrors the directory tree on disk. Knowing this makes it straightforward to find the source of any Acron class when you want to understand exactly what it does.

The complete import block at the top of the final Hello World program is:

from math import pi, sin, cos

from direct.showbase.ShowBase import ShowBase
from direct.task import Task
from direct.actor.Actor import Actor
from direct.interval.IntervalGlobal import Sequence
from acron.core import Point3

Each line pulls in exactly what is needed from a specific location. Nothing more, nothing less.

The random Module

Games need unpredictability. Python’s random module provides pseudorandom numbers — not truly random, but impossible to distinguish from random by looking at the output:

import random

# random float in [0.0, 1.0)
drop_chance = random.random()
if drop_chance < 0.05:
    spawn_item("legendary_sword")

# random integer in [low, high] inclusive
damage = random.randint(8, 16)

# pick one element from a list at random
enemy_type = random.choice(["goblin", "orc", "troll"])

Randomness affects level generation, loot drops, AI decisions, procedural animation variation — almost every interesting game system uses it.

Your Own Modules

Any .py file you create is a module. A typical small Acron project:

game/
├── main.py        ← entry point, contains MyApp(ShowBase)
├── player.py      ← Player class
├── enemy.py       ← Enemy class
└── constants.py   ← shared values (MAX_HEALTH, SPAWN_POINT, …)

In main.py:

from player import Player
from enemy import Enemy
from constants import SPAWN_POINT

Split code this way to keep each file focused and each class easy to find. Avoid one enormous file — it becomes hard to navigate and hard to test.