The Ghost Class

The Mastermind • Orchestration • Animation • Logic

<The_Big_Picture />

The Ghost class is where the magic happens. It brings everything together!

It doesn't just look pretty; it moves. The Ghost class demonstrates Composition by "owning" a Head (Disk) and two Eyes (Eyeballs). It also manages complex State (position, velocity) and Behavior (bouncing off walls, coordinating eye movement).

When the Ghost moves, it's responsible for moving its head and eyes along with it. This is a key principle of encapsulation—the outside world just says "ghost.update()", and the Ghost handles all the internal details.


1. The Constructor: Assembling the Spirit

Unlike the simpler classes, the Ghost takes a lot of parameters. Notice how we pass in an existing head object (Disk). We also calculate random velocities if none are provided.

ghost3.py (Snippet: __init__)
8 class Ghost:
22    def __init__(self, head, ht, num_feet, eye_color, eye_base_colors, eye_span_factor=0.85, 
23                 start_pos=None, velocity=None, canvas_width=800, canvas_height=600, feet_round=True):
24
36        self.head = head
37        self.b_color = self.head.bg_color  # Body matches head color
38        self.ht = self.head.radius + ht     # Total height
39        self.wd = 2 * head.radius
40        self.num_feet = num_feet
49        
50        # Initialize position (use head center as default)
51        if start_pos is None:
52            self.position = list(head.center)
53        else:
54            self.position = list(start_pos)
55        
56        # Initialize velocity (random if not specified)
57        if velocity is None:
58            # Random velocity between 1.0 and 8.0
59            self.velocity = [random(1.0, 8.0), random(1.0, 8.0)]
60        else:
61            self.velocity = list(velocity)
62        
63        self.create_eyes() # Helper method to make Eyeball objects
64    #end init

2. The Update Loop: It's Alive!

This method is called every frame of the animation loop. It embodies the logic of the ghost.

  1. Move: Add velocity to current position.
  2. Bounce: Check if we hit a wall (check_bounds).
  3. Sync Parts: Crucial step! The head and eyes must move to the new position.
  4. Animate Eyes: The Eyeball.look_in_direction() method is called so the ghost looks where it's going!
ghost3.py (Snippet: update)
91    def update(self):
97        # Update position based on velocity
98        self.position[0] += self.velocity[0]
99        self.position[1] += self.velocity[1]
100        
101        # Check boundaries and bounce
102        self.check_bounds()
103        
104        # Update head center to match current position
105        self.head.set_center((self.position[0], self.position[1]))
106        
107        # Update eye positions to match new head position
108        self.update_eye_positions()
109        
110        # Make eyes look in direction of movement
111        self.left_eye.look_in_direction(self.velocity[0], self.velocity[1])
112        self.right_eye.look_in_direction(self.velocity[0], self.velocity[1])
113    #end update

3. Rendering: Drawing the Nightmare

Finally, the ghost draws itself. It delegates the complex drawing of the head and eyes to their respective classes, focusing only on drawing its own body and feet.

ghost3.py (Snippet: render)
149    def render(self):
154        # Draw the head (a circular Disk)
155        self.head.render()
156        
157        # Draw the body (rectangular section below head)
158        fill(self.b_color)
159        noStroke()
160        rect(self.head.center[0] - self.head.radius, self.head.center[1], self.wd, self.ht)
161        
162        # ... (Feet drawing logic omitted for brevity) ...
188        
189        # Draw the eyes last so they appear on top
190        self.left_eye.render()
191        self.right_eye.render()
192    #end render