Halloween: Michael Myers & Eyesy

by

Micheal Myers is a spooky, scary slasher and I've wanted to get more in the Halloween spirit. The opening credit sequence for John Carpenter and Debra Hill's Halloween was a perfect opportunity to create a new Eyesy mode. Replicating a flickering pumpkin in the dark slowly zooming in as the ominous piano dings is the final goal here.

These are the comparison shots. Don't mind the quality:

Halloween Screen Halloween Title Sequence

The Night We Went Mike

The main features of this Mode are:

  • Pumpkin will zoom in and out while glowing to the audio input volume level
  • Pumpkin and Text can be moved using the Eyesy knobs
  • Eyesy Knob5 will change text display modes between nothing, the phrase "Halloween", and a scrolling display of the Halloween (1979) script

Michael doesn't become Myers without the background of murdering his sister in cold blood and being placed in a mental institution, so we need some set up and global variables.

grow = False
pumpkin_growth = 0
alpha = 100
alpha_prev = 0
start_line = 0
end_line = 25
counter = 0

The grow variables control the pumpkin zoom rates, the alpha variables control the pumpkin image alpha value (or transparency), and the line variables and counter control the rate and number of lines from the movie script displayed.

def setup(screen, etc):
    global xr, yr, image, font, base_path, script, script_line, prime_font
    xr = etc.xres
    yr = etc.yres
    base_path = etc.mode_root
    image = pygame.image.load(base_path + 'Images/pumpkin.png').convert()
    font = pygame.font.Font(base_path + 'Fonts/scary-halloween/Scary Halloween Font.ttf', 60)
    prime_font = pygame.font.Font(base_path + 'Fonts/courier-prime/CourierPrime-Regular.ttf', 15)
    with open(base_path + '/Text/halloween_script.txt', 'r') as script:
        script_line = script.readlines()
    pass

The setup function will load screen resolution, images, fonts, and text for the main draw function.

I can't name the main function knife_stabber so just draw will have to do. It'll call two internal functions. The first is _pumpkin_lighting that adjusts alpha and image size levels. Knob5 will control what text should appear, if it is in script mode it will call the second internal function _script_display; otherwise, the phrase "Halloween" or nothing will appear on the screen.

def draw(screen, etc):
    pygame.time.Clock().tick(20)
    etc.color_picker_bg(0)
    
    _pumpkin_lighting(screen, etc)
    
    if etc.knob5 >= 0.5:
        _script_display(screen, etc)
    elif etc.knob5 > 0:
        text = font.render('Halloween', True, (235, 97, 35))
        screen.blit(text, (int(xr * etc.knob3), int(yr * etc.knob4)))
    else:
        pass

Laurie has to rely on what little lighting she can to spot her murderous stalker; thankfully, she's blasting some tunes that are causing the pumpkin light to flash as the audio level changes. An image with an alpha background can lower the Alpha levels out of 255 to make the background more transparent. Since our pumpkin image already looks like a bright flame is inside it, we adjust the transparency or alpha level up and down based on the average audio input level to simulate a flickering Jack-O-Lantern.

The image location can be ajusted using Knob1 and Knob2, while the pumpkin size will grow and subtract based on the thresholds set.

def _pumpkin_lighting(screen, etc):
    global alpha, alpha_prev, grow, pumpkin_growth
    pumpkin_image_size = (
        int(image.get_width()/4 + pumpkin_growth),
        int(image.get_height()/4 + pumpkin_growth)
        )
    img = pygame.transform.scale(image, pumpkin_image_size)
    alpha_threshold = 200
    alpha_new = sum(map(abs, etc.audio_in[0:50]))/2500
    alpha = alpha + alpha_new - alpha_prev
    alpha_prev = alpha_new
    img.set_alpha(alpha_threshold) if alpha > alpha_threshold else img.set_alpha(alpha)
    
    if grow:
        pumpkin_growth -= 1
        if pumpkin_growth <= 0: grow = False
    else:
        pumpkin_growth += 1
        if pumpkin_growth >= 500: grow = True
    
    img_dest = (int(xr * etc.knob1), int(yr * etc.knob2))
    
    screen.blit(img, img_dest)

We need to let the rest of this horror show play out in script form. The start and end lines can be adjusted to display more or less of the current script page. We'll increment the lines shown to create a scrolling effect based on a counter. Knob4 can control the text scroll rate. Knob3 can be used to change the screen display location of the script.

def _script_display(screen, etc):
    global start_line, end_line, counter, script_line, prime_font
    if start_line >= len(script_line):
        start_line = 0
        end_line = 20
    elif end_line > len(script_line) - 1:
        start_line = len(script_line) - 1
        end_line = len(script_line)
    
    script_lines = script_line[start_line:end_line]
    for i, l in enumerate(script_lines):
        text = prime_font.render(l.replace('\n', ' '), True, (235, 97, 35))
        screen.blit(text, (int(xr * etc.knob3), yr/10 + i*20))
    
    if counter > 20 * etc.knob4:
        start_line += 1
        end_line += 1
        counter = 0
    else:
        counter += 1

As Michael gets to the end of his murder mowdown to be thwarted by an unsuspecting teen, this video visualizes how the Eyesy mode should play out:

Beware and be safe out there. You never know what's lurking in the shadows.

Resources:

Halloween GitHub
Eyesy Manual
Patch Storage Halloween
Rodeo Round Up Eyesy Guide

Share this post