# data[].attributes.body
If you/your child is interested in making the additional modifications and features (listed below), the additional code required and lessons covered in the book are given, chapter by chapter, in the program files linked below.

# data[].attributes.body
Follow Step 5 of Installing Python and Pygame to ensure both the game assets and program files are inside your vampire_pizza_directory. If these items are not in the same folder, your code will no run correctly!

# data[].attributes.body
Coding this game was the meat and potatoes of our camp! It allowed us to put into practice the concepts we learned in other activities, as well as several others, in order to create a playable and detailed tower-defense-style game.

Students put in a lot of hard work and coded hundreds of lines of code this week.We still learned a lot of very important coding concepts (described in the About this Camp Overview section) and gained the necessary skill of debugging!

The above file is the completed and working base code (through Chapter 13). Students can use this file to compare and continue working on their own code and/or use is as a launching pad for working on Part 3 -- Break This Code.

Please use the linked file rather than the one seen on the GitHub linked on odddot.com as there are several bugs on that version that have been taken care of for you above!

# data[].attributes.attachment_link.readable_text
#Set-up Game

#import libraries
import pygame
from pygame import *
from random import randint

#initialize pygame
pygame.init()

#set up clock
clock = time.Clock() 

#-----------------------------
#Define constant variables

#Define the parameters of the game window
WINDOW_WIDTH = 1100
WINDOW_HEIGHT = 600
WINDOW_RES = (WINDOW_WIDTH, WINDOW_HEIGHT)

# Define the parameters of each tile
WIDTH = 100
HEIGHT = 100

# Define colors
WHITE = (255, 255, 255)

#Set up rates
SPAWNRATE = 360
FRAMERATE = 60

#Set up counters
STARTING_BUCKS = 15
BUCK_RATE = 120
STARTING_BUCK_BOOSTER = 1
MAX_BAD_REVIEWS = 3
WIN_TIME = FRAMERATE * 60 * 3

#Define speeds
REG_SPEED = 2
SLOW_SPEED = 1

#--------------------------------------------------------------
#Load Assets 


#create window
GAME_WINDOW = display.set_mode(WINDOW_RES)
display.set_caption('Attack of the Vampire Pizzas!')

#set up enemy imgage
pizza_img = image.load('vampire.png')
pizza_surf = Surface.convert_alpha(pizza_img)
VAMPIRE_PIZZA = transform.scale(pizza_surf, (100, 100))

#set up background image
background_img = image.load('restaurant.jpg')
background_surf = Surface.convert_alpha(background_img)
BACKGROUND = transform.scale(background_surf, (WINDOW_RES))

# tile trap images
garlic_img = image.load('garlic.png')
garlic_surf = Surface.convert(garlic_img)
GARLIC = transform.scale(garlic_surf, (WIDTH, HEIGHT))
GARLIC.set_alpha(127)
cutter_img = image.load('pizzacutter.png')
cutter_surf = Surface.convert(cutter_img)
CUTTER = transform.scale(cutter_surf, (WIDTH, HEIGHT))
CUTTER.set_alpha(127)
pepperoni_img = image.load('pepperoni.png')
pepperoni_surf = Surface.convert(pepperoni_img)
PEPPERONI = transform.scale(pepperoni_surf, (WIDTH, HEIGHT))
PEPPERONI.set_alpha(127)

#---------------------------------------------
#Set up classes

#Create an enemy class
class VampireSprite(sprite.Sprite):

    #This function creates an instance of the enemy
    def __init__(self):
        super().__init__()
        self.speed = REG_SPEED
        self.lane = randint(0, 4)
        all_vampires.add(self)
        self.image = VAMPIRE_PIZZA.copy()
        y = 50 + self.lane * 100
        self.rect = self.image.get_rect(center=(1100, y))
        self.health = 150

    #This function moves the enemies from right to left and destroys them after they've left the screen
    def update(self, game_window, counters):
        game_window.blit(BACKGROUND, (self.rect.x, self.rect.y), self.rect)
        self.rect.x -= self.speed
        if self.health <= 0 or self.rect.x <= 100:
            self.kill()
            if self.rect.x <= 100:
                counters.bad_reviews += 1
        else:
            game_window.blit(self.image, (self.rect.x, self.rect.y))

    def attacked_by(self, tile):
        if tile.trap == SLOW:
            self.speed = SLOW_SPEED
        if tile.trap == DAMAGE:
            self.health -= 1

class Counters(object):

    def __init__(self, pizza_bucks, buck_rate, buck_booster, timer):
        self.loop_count = 0
        self.display_font = pygame.font.Font('pizza_font.ttf', 25)
        self.pizza_bucks = pizza_bucks
        self.buck_rate = buck_rate
        self.buck_booster = buck_booster
        self.bucks_rect = None
        self.timer = timer
        self.timer_rect = None
        self.bad_reviews = 0
        self.bad_reviews_rect = None

    def increment_bucks(self):
        if self.loop_count % self.buck_rate == 0:
            self.pizza_bucks += self.buck_booster

    def draw_bucks(self, game_window):
        if bool(self.bucks_rect):
            game_window.blit(BACKGROUND, (self.bucks_rect.x, self.bucks_rect.y), self.bucks_rect)
        bucks_surf = self.display_font.render(str(self.pizza_bucks), True, WHITE)
        self.bucks_rect = bucks_surf.get_rect()
        self.bucks_rect.x = WINDOW_WIDTH - 50
        self.bucks_rect.y = WINDOW_HEIGHT - 50
        game_window.blit(bucks_surf, self.bucks_rect)

    def draw_bad_reviews(self, game_window):
        if bool(self.bad_reviews_rect):
            game_window.blit(BACKGROUND, (self.bad_reviews_rect.x, self.bad_reviews_rect.y), self.bad_reviews_rect)
        bad_reviews_surf = self.display_font.render(str(self.bad_reviews), True, WHITE)
        self.bad_reviews_rect = bad_reviews_surf.get_rect()
        self.bad_reviews_rect.x = WINDOW_WIDTH - 150
        self.bad_reviews_rect.y = WINDOW_HEIGHT - 50
        game_window.blit(bad_reviews_surf, self.bad_reviews_rect)

    def draw_time(self, game_window):
        if bool(self.timer_rect):
            game_window.blit(BACKGROUND, (self.timer_rect.x, self.timer_rect.y), self.timer_rect)
        timer_surf = self.display_font.render(str(int((WIN_TIME - self.loop_count) / FRAMERATE)), True, WHITE)
        self.timer_rect = timer_surf.get_rect()
        self.timer_rect.x = WINDOW_WIDTH - 250
        self.timer_rect.y = WINDOW_HEIGHT - 50
        game_window.blit(timer_surf, self.timer_rect)

    def update(self, game_window):
        self.loop_count += 1
        self.increment_bucks()
        self.draw_bucks(game_window)
        self.draw_bad_reviews(game_window)
        self.draw_time(game_window)


#Set up the different kinds of traps
class Trap(object):

    def __init__(self, trap_kind, cost, trap_img):
        self.trap_kind = trap_kind
        self.cost = cost
        self.trap_img = trap_img


class TrapApplicator(object):

    def __init__(self):
        self.selected = None

    def select_trap(self, trap):
        if trap.cost <= counters.pizza_bucks:
            self.selected = trap

    def select_tile(self, tile, counters):
        self.selected = tile.set_trap(self.selected, counters)


#Create a class of sprites. Each tile has an invisible interactive field attached to it which is a sprite in this class. 
class BackgroundTile(sprite.Sprite):

    def __init__(self):
        super().__init__()
        self.trap = None

class PlayTile(BackgroundTile):

    def set_trap(self, trap, counters):
        if bool(trap) and not bool(self.trap):
            counters.pizza_bucks -= trap.cost
            self.trap = trap
            if trap == EARN:
                counters.buck_booster += 1
        return None

    def draw_trap(self, game_window, trap_applicator):
        if bool(self.trap):
            game_window.blit(self.trap.trap_img, (self.rect.x, self.rect.y))


class ButtonTile(BackgroundTile):

    def set_trap(self, trap, counters):
        if counters.pizza_bucks >= self.trap.cost:
            return self.trap
        return trap

    def draw_trap(self, game_window, trap_applicator):
        if bool(trap_applicator.selected) and trap_applicator.selected == self.trap:
            game_window.blit(self.trap.trap_img, (self.rect.x, self.rect.y))

class InactiveTile(BackgroundTile):

    def set_trap(self, trap, counters):
        return trap

    def draw_trap(self, game_window, trap_applicator):
        pass


#-------------------------------------------------------------
#Create class instances

#create a sprite group for all the VampireSprite instances
all_vampires = sprite.Group()

counters = Counters(STARTING_BUCKS, BUCK_RATE, STARTING_BUCK_BOOSTER, WIN_TIME)

SLOW = Trap('SLOW', 5, GARLIC)
DAMAGE = Trap('DAMAGE', 3, CUTTER)
EARN = Trap('EARN', 7, PEPPERONI)

trap_applicator = TrapApplicator()


#--------------------------------------------------------------
# Initialize and draw Background Grid

# Create an empty list to hold the tile grid
tile_grid = []
# Populate the grid
tile_color = WHITE
for row in range(6):
    row_of_tiles = []
    tile_grid.append(row_of_tiles)
    for column in range(11):
        if column <= 1:
            new_tile = InactiveTile()
        else:
            if row == 5:
                if 1 < column < 5:
                    new_tile = ButtonTile()
                    new_tile.trap = [SLOW, DAMAGE, EARN][column - 2]
                else:
                    new_tile = InactiveTile()
            else:
                new_tile = PlayTile()
        new_tile.rect = pygame.Rect(WIDTH * column, HEIGHT * row, WIDTH, HEIGHT)
        row_of_tiles.append(new_tile)
        if row == 5 and 1 < column < 5:
            BACKGROUND.blit(new_tile.trap.trap_img, (new_tile.rect.x, new_tile.rect.y))
        if column != 0 and row != 5:
            if column != 1: 
                draw.rect(BACKGROUND, tile_color, (WIDTH * column, HEIGHT * row, WIDTH, HEIGHT), 1)

GAME_WINDOW.blit(BACKGROUND, (0,0))




#--------------------------------------------------------------------------------------------------------------------------------------
#Start Main Game Loop

#Game Loop
running = True
exited = True
while running: 

#------------------------------------------
#Check for events

    #checking for and handling events
    for event in pygame.event.get():

        #exit loop on quit
        if event.type == QUIT: 
            running = False
            exited = False

        #Set up the background tiles to respond to a mouse click
        elif event.type == pygame.MOUSEBUTTONDOWN:
            x, y = pygame.mouse.get_pos()
            trap_applicator.select_tile(tile_grid[y // 100][x // 100], counters)


#-------------------------------------------------
#Create VampireSprite instances

    if randint(1, SPAWNRATE) == 1:
        VampireSprite()

#------------------------------------------------
#Set up collision detection

    #draw the background grid
    for tile_row in tile_grid:
        for tile in tile_row:
            if bool(tile.trap):
                GAME_WINDOW.blit(BACKGROUND, (tile.rect.x, tile.rect.y), tile.rect)

    #set up collision detection
    for vampire in all_vampires:
        tile_row = tile_grid[vampire.rect.y // 100]
        vampire_left_side_x = vampire.rect.x // 100
        vampire_right_side_x = (vampire.rect.x + vampire.rect.width) // 100
        if -1 < vampire_left_side_x < 10:
            left_tile = tile_row[vampire_left_side_x]
        else:
            left_tile = None
        if -1 < vampire_right_side_x < 10:
            right_tile_wall = tile_row[vampire_right_side_x]
        else:
            right_tile = None
        if bool(left_tile):
            vampire.attacked_by(left_tile)
        if bool(right_tile) and right_tile.x != left_tile.x:
            vampire.attacked_by(right_tile)

#-------------------------------------------------
#Set win/lose conditions

    if counters.bad_reviews >= MAX_BAD_REVIEWS:
        running = False

    if counters.loop_count > WIN_TIME:
        running = False

#-------------------------------------------------
#Update displays
    for vampire in all_vampires:
        vampire.update(GAME_WINDOW, counters)

    for tile_row in tile_grid:
        for tile in tile_row:
            tile.draw_trap(GAME_WINDOW, trap_applicator)

    counters.update(GAME_WINDOW)
    display.update()

    #set the framerate
    clock.tick(FRAMERATE)

#Close Main Game Loop
#------------------------------------------------------------------------------------------------------------------------
#End of game loop

#Set end game message
end_font = pygame.font.Font('pizza_font.ttf', 50)

if exited:
    if counters.bad_reviews >= MAX_BAD_REVIEWS:
            end_surf = end_font.render('Game Over', True, WHITE)
    else:
            end_surf = end_font.render('You Win!!', True, WHITE)
    GAME_WINDOW.blit(end_surf, (350, 200))
    display.update()

#-------------------
#Enable exit from end game loop
while exited:
    for event in pygame.event.get():
        if event.type == QUIT: 
            exited = False
    clock.tick(FRAMERATE)

#Close end game loop
#--------------------- 

#Clean-up Game
pygame.quit()

# data[].attributes.body
This linked file was used to help the students to become familiar with the syntax of defining and instantiating (creating) a class object in Python.

A class is one of the core ideas of object-oriented programming. A class can hold a multiple different things called methods and attributes. It can also contain other classes, making it a "super class."

When this code is run, it takes inputs (using the input( ) function) from the user and prints (using the print( ) function) certain responses depending on the user input.

# data[].attributes.attachment_link.readable_text
class Monster(object):                  # Create the superclass
    eats = 'food'                       # Set up class attribute, same for all classes
    def __init__(self, name):           # Define the __init__ method
        self.name = name                # Set up an instance attribute, different for each instance

    def speak(self):                    # Define a method for speaking behavior
        print(self.name + 'speaks')

    def eat(self, meal):                # Deine a method for eating behavior
        if meal == self.eats:
            print('yum!')
        else:
            print('yuck!')


class FrankenBurger(Monster):           # Create a subclass of Monster
    eats = 'hamburger patties'          # Set up a class attribute

    def speak(self):                    # define any methods that are different from the superclass
        print('My name is ' + self.name + 'Burger')


class CrummyMummy(Monster):             # Create a subclass of Monster
    eats = 'chocolate chips'            # Set up a class attribute

    def speak(self):                    # define any methods that are different from the superclass
        print('My name is ' + self.name + 'Mummy')


class WereWatermelon(Monster):          # Create a subclass of Monster
    eats = 'watermelon juice'           # Set up a class attribute

    def speak(self):                    # define any methods that are different from the superclass
        print('My name is Were' + self.name)

        


monster_selection = input('What kind of monster do you want to create? Select frankenburger, crummymummy, or werewatermelon.')
monster_name = input('What do you want to name your monster?')
monster_meal = input('What will you feed your monster?')

if monster_selection == 'frankenburger':
    monster_type = FrankenBurger
elif monster_selection == 'crummymummy':
    monster_type = CrummyMummy
elif monster_selection == 'werewatermelon':
    monster_type = WereWatermelon
else:
    monster_type = Monster

my_monster = monster_type(monster_name)
my_monster.speak()
my_monster.eat(monster_meal)

# data[].attributes.body
Follow the link to download the latest version of Python

# data[].attributes.attachment_link.readable_text
Information about specific ports, and developer info

OpenPGP Public Keys

Source and binary executables are signed by the release manager or binary builder using their OpenPGP key. Release files for currently supported releases are signed by the following:

Release files for older releases which have now reached end-of-life may have been signed by one of the following:

You can import a person's public keys from a public keyserver network server you trust by running a command like:

or, in many cases, public keys can also be found at keybase.io. On the version-specific download pages, you should see a link to both the downloadable file and a detached signature file. To verify the authenticity of the download, grab both files and then run this command:

gpg --verify Python-3.6.2.tgz.asc

Note that you must use the name of the signature file, and you should use the one that's appropriate to the download you're verifying.

(These instructions are geared to GnuPG and Unix command-line users.)

macOS Installer Packages

Installer packages for Python on macOS downloadable from python.org are signed with with an Apple Developer ID Installer certificate.

As of Python 3.11.4 and 3.12.0b1 (2023-05-23), release installer packages are signed with certificates issued to the Python Software Foundation (Apple Developer ID BMM5U3QVKW)).

Installer packages for previous releases were signed with certificates issued to Ned Deily (DJ3H93M7VJ).

Other Useful Items

Looking for 3rd party Python modules? ThePackage Index has many of them.

You can view the standard documentation online, or you candownload it in HTML, PostScript, PDF and other formats. See the mainDocumentation page.

Information on tools for unpacking archive files provided on python.org is available.

Tip: even if you download a ready-made binary for your platform, it makes sense to also download thesource. This lets you browse the standard library (the subdirectoryLib) and the standard collections of demos (Demo) and tools (Tools) that come with it. There's a lot you can learn from the source!

There is also a collection of Emacs packages that the Emacsing Pythoneer might find useful. This includes major modes for editing Python, C, C++, Java, etc., Python debugger interfaces and more. Most packages are compatible with Emacs and XEmacs.

Want to contribute?

Want to contribute? See the Python Developer's Guide to learn about how Python development is managed.

# data[].attributes.attachment_link.keywords[]
python programming language object oriented web free open source software license documentation download community

# data[].attributes.attachment_link.description
The official home of the Python Programming Language

# data[].attributes.body
For this activity, we created our own Mad Libs using Python's input( ) and print( ) functions.

input( ) will prompt the user to type something in the command line then store the user's response into a predefined variable

color = input('What is your favorite color?')

print( ) will display a pre-coded message onto the command line

print('Your favorite color is ' + color + '. That's mine, too!')

# data[].attributes.body
To download the additional assets required for Part 3, follow the above link and click "Download image asset package!"

Click the .zip file downloaded to open the images

Copy and paste all images (it is not necessary to copy the folders included and shown at the top) into vampire_pizza_directory

If you do not put the images in the correct location, you will not be able to use them in your code!

# data[].attributes.attachment_link.readable_text
Make it! Code it! Break it! Mod it!

Free

assets

online

Kickstand

Cover

6.5" x 9"

288

Pages

CODE THIS GAME! is a nonfiction visual guide that teaches young readers, 10-14, how to program and create their very own video game. Each chapter introduces key coding concepts as kids create an action strategy game in Python, an open-source programming language. A built-in kickstand allows readers to stand the spiral-bound book upright so they can read, program, and play their game simultaneously.
The first part of the book guides readers through the world of computer science and game development, with easy-to-follow step-by-step instructions. Kids will build a strategy action game where the player must defeat vampire pizzas. The second part of the book teaches readers to modify their game and go where their imaginations lead them by incorporating downloadable art assets. By the time kids finish the book, they'll have mastered basic coding concepts and created a personalized game.

The book is written by computer science educator and a writer of the CSTA Computer Science Standards Meg Ray, and vividly illustrated by Keith Zoo.

# data[].attributes.body
In IDLE, go to File -> New File

IDLE will open a new untitled program file window (be sure you are seeing a program file and not a shell window, you should not see any red arrows ( >> ) on the left side of your screen)

File -> Save As

Browse to the directory you wish to save the file in (this could be vampire_pizza_directory or another directory you created using Step 4 of Installing Python and Pygame)

Name the file (make sure sure there are no spaces in your file name, only letters and underscores!)

Click "Save"

# data[].attributes.body
Double click the download to open the Python Installer

Be sure to select "Add Python to PATH" (towards the bottom of the installer window)

Click Install Now

# data[].attributes.body
This week we worked through "Code This Game!" by Meg Ray. This instructional book walked the students through some very important coding concepts (listed below) and building a game called Attack of the Vampire Pizzas! where the goal is to prevent the vampire pizzas from reaching the delivery trucks using a variety of different traps and boosts (think Plants vs. Zombies).

What we learned this week:

Classes (described in greater detail under the Monster Class Activity section

Methods

Ex: def x(self):

Attributes

Ex: self.x = x

Loops:

For Loops

Ex: for x in range(y):

While Loops

Ex: while x:

Booleans

Ex: x = True, y = False

Variables

Definitions

Ex: x = 100

Increment/Decrement

Ex: x += 1, y -=1

Game Window

Defining the size

display.set_mode(WIDTH, HEIGHT)

Displaying images

game_window.blit(self.image,      (self.rect.x, self.rect.y))

draw.circle(GAME_WINDOW, (r,g,b), (x,y), radius, thickness)

draw.rect(GAME_WINDOW, (r,g,b), (x,y, width, height), thickness)

Conditionals:

If/Else statements

Ex: if x:, elif y:, else:

Thank you for the week! It was super awesome to get to know all of you/your kids. I hope they had fun, learned something this week, and formed an interest in this kind of stuff!

The completed code (through Chapter 13) is attached in the Attack of the Vampire Pizzas! Overview section. This can be used to help the students finish up their basic game and/or be used as a base line to work on Part 3 - Break This Game!, where students will modify, hack, and rebuild their game to make it even more fun and spectacular.

# data[].attributes.body
In IDLE, go to File -> Open

Browse to the directory you wish to save the file in (this could be vampire_pizza_directory or another directory you created using Step 4 of Installing Python and Pygame)

Double click on the program file you wish to open (be sure you are seeing a program file window and not a shell window, you should not see any red arrows ( >> ) on the left side of your screen)

# data[].attributes.body
Windows OS Computers

Type "Command Prompt" in your Windows search bar and open the application

In Command Prompt, Type "python --version" to verify Python installation

Type "python -m pip install -U pygame --user" to install Python's game development module, called Pygame

Wait for the message "successfully installed pygame"

iOS Computers

Type "Terminal" in the search bar and open the application

In Terminal, Type "python3 --version" to verify Python installation

Type "python3 -m pip install -U pygame --user"

Wait for the message "successfully installed pygame"

# data[].attributes.body
MadLib Activity

Students programmed their own MadLib using Python's input( ) function to prompt the user for a variety of word types (different nouns, verbs, etc.) then used Python's print( ) function to display their story using the user inputs.

Began working on the Vampire Pizza Attack! game

Students worked through roughly Chapters 1 - 2 of "Code This Game!" to create their game window, add their background and first enemy image to the screen.

# data[].attributes.body
In IDLE, with your program file window selected, go to Run -> Run this Module

# data[].attributes.body
Create a new directory (folder) using the command line

While still in Command Prompt or Terminal, type "mkdir vampire_pizza_directory" to create the directory

Type "cd vampire_pizza_directory" to go into the new directory

We practiced getting to this folder several times through out the week, but the path will be slightly different on your home computer. A general guide to locate this folder on your computer is as follows:

Windows OS Computers
** Open the Files app
-> This PC
-> Local Disk (C:)
-> Users
-> ** Your User Profile **
-> vampire_pizza_directory

iOS Computers
** Open Finder App
-> This Mac
-> vampire_pizza_directory

Also feel free to just search your computer for this folder!

# data[].attributes.body
Continued working on the Vampire Pizza Attack! game

Students worked through roughly Chapters 3 - 6 of "Code this Game!" to practice drawing and displaying shapes to the game window, create the background grid, and define and create their enemy object.

# data[].attributes.body
Download MadLib.py and/or VampirePizzaAttack.py. Once downloaded drag these program files into the vampire_pizza_attack folder.

To download the additional assets required for Part 3, follow the above link and click "Download image asset package!"

Click the .zip file downloaded to open the images

Copy and paste all images (it is not necessary to copy the folders included and shown at the top) into vampire_pizza_directory

** If your VampirePizzaAttack.py and game asset images are not in the same folder, your game will not run correctly! **

# data[].attributes.attachment_link.readable_text
Make it! Code it! Break it! Mod it!

Free

assets

online

Kickstand

Cover

6.5" x 9"

288

Pages

CODE THIS GAME! is a nonfiction visual guide that teaches young readers, 10-14, how to program and create their very own video game. Each chapter introduces key coding concepts as kids create an action strategy game in Python, an open-source programming language. A built-in kickstand allows readers to stand the spiral-bound book upright so they can read, program, and play their game simultaneously.
The first part of the book guides readers through the world of computer science and game development, with easy-to-follow step-by-step instructions. Kids will build a strategy action game where the player must defeat vampire pizzas. The second part of the book teaches readers to modify their game and go where their imaginations lead them by incorporating downloadable art assets. By the time kids finish the book, they'll have mastered basic coding concepts and created a personalized game.

The book is written by computer science educator and a writer of the CSTA Computer Science Standards Meg Ray, and vividly illustrated by Keith Zoo.

# data[].attributes.body
Monster Class Activity

Students used a pre-programmed file to obtain a better understanding of how to define and instantiate (create) class objects.

Continued working on the Vampire Pizza Attack! game

Students worked through roughly Chapters 7 - 9 of "Code this Game!" to make their enemies move, create interactive fields, and create collision detection.

# data[].attributes.body
Open IDLE,  Python's own Integrated Development Environment (IDE). This was downloaded as a part of a Python package. To open it, just search your computer for IDLE

Open your program file (.py) of choice in IDLE:

1. File -> Open

2. Browse for the vampire_pizza_directory using the path given in Step 4

Make sure that when trying to edit a program file in IDLE you are not in the Python shell! If you are in the shell you will see red arrows ( >> ) over towards the left hand side of the window.

# data[].attributes.body
Continued working on the Vampire Pizza Attack! game

Students worked through roughly Chapters 10-11 of "Code this Game!" to add a points system and apply traps for the Vampire Pizzas.

# data[].attributes.body
Continued working on the Vampire Pizza Attack! game

Students worked through Chapters 12 - 13 to finish up the basic concepts of their game by connecting the traps to the grid and add win/lose conditions

Camp Celebrations!

Thank you for the week! It was super awesome to get to know all of you/your kids. Hopefully they had fun, learned something this week, and formed an interest in this kind of stuff!

The completed code (through Chapter 13) is attached in the Vampire Pizza Attack! Overview section. This can be used to help the students finish up their basic game and/or be used as a base line to work on Part 3 - Break This Game!, where students will modify, hack, and rebuild their game to make it even more fun and spectacular.

# data[].attributes.attachment_link.readable_text
import pygame 
from pygame import * 
from random import randint 
pygame.init() 
 
clock = time.Clock() 
 
WINDOW_WIDTH = 1100 
WINDOW_HEIGHT = 600 
WINDOW_RES = (WINDOW_WIDTH, WINDOW_HEIGHT) 
 
WIDTH = 100 
HEIGHT = 100 
 
WHITE = (0, 255, 200) 
WHITE2 = (255, 0, 0)
WHITE3 = (0, 0, 255)
SPAWN_RATE = 360 
FRAME_RATE = 60

STARTING_BUCKS = 15
BUCK_RATE = 120
STARTING_BUCK_BOOSTER = 1

MAX_BAD_REVIEWS = 5
WIN_TIME = FRAME_RATE* 60 * 1
 
REG_SPEED = 2 
SLOW_SPEED = 1 
 
GAME_WINDOW = display.set_mode(WINDOW_RES) 
display.set_caption('Attack of the anchovy cannons!') 
 
background_img = image.load('galaxy.jpg') 
background_surf = Surface.convert_alpha(background_img) 
BACKGROUND = transform.scale(background_surf, WINDOW_RES) 
 
pizza_img = image.load('anchovy-cannon.png') 
pizza_surf = Surface.convert_alpha(pizza_img) 
VAMPIRE_PIZZA = transform.scale(pizza_surf, (WIDTH, HEIGHT)) 
garlic_img = image.load('oil-can.png') 
garlic_surf = Surface.convert_alpha(garlic_img) 
GARLIC = transform.scale(garlic_surf, (WIDTH, HEIGHT)) 
 
 
 
cutter_img = image.load('sad-hammer.png') 
cutter_surf = Surface.convert_alpha(cutter_img) 
CUTTER = transform.scale(cutter_surf, (WIDTH, HEIGHT)) 
 
pepperoni_img = image.load('laptop.png') 
pepperoni_surf = Surface.convert_alpha(pepperoni_img) 
PEPPERONI = transform.scale(pepperoni_surf, (WIDTH, HEIGHT))
class VampireSprite(sprite.Sprite): 
    def __init__(self): 
        super().__init__() 
        self.speed = 2 
        self.speed = REG_SPEED 
        self.lane = randint(0, 4) 
        all_vampires.add(self) 
        self.image = VAMPIRE_PIZZA.copy() 
        y = 50 + self.lane * 100 
        self.rect = self.image.get_rect(center = (1100, y)) 

class VampireSprite(sprite.Sprite): 
    def __init__(self): 
        super().__init__() 
        self.speed = REG_SPEED 
        self.lane = randint(0, 4) 
        all_vampires.add(self) 
        self.image = VAMPIRE_PIZZA.copy() 
        y = 50 + self.lane * 100 
        self.rect = self.image.get_rect(center = (1100, y)) 
        self.health = 100
    def update(self, game_window, counters): 
        game_window.blit(BACKGROUND, (self.rect.x, self.rect.y), self.rect) 
        self.rect.x -= self.speed
        if self.health <= 0 or self.rect.x <= 100:
            self.kill()
            if self.rect.x <= 100:
                counters.bad_reviews += 1
        else:
            game_window.blit(self.image, (self.rect.x, self.rect.y))

    def attack(self, tile): 
        if tile.trap == SLOW: 
            self.speed = SLOW_SPEED 
        if tile.trap == DAMAGE: 
            self.health -= 1 
        
 
class Counters(object): 
    def __init__(self, pizza_bucks, buck_rate, buck_booster, timer): 
        self.loop_count = 0 
        self.display_font = font.Font('pizza_font.ttf', 25) 
        self.pizza_bucks = pizza_bucks 
        self.buck_rate = buck_rate 
        self.buck_booster = buck_booster 
        self.bucks_rect = None
        self.timer = timer 
        self.timer_rect = None 
        self.bad_reviews = 0 
        self.bad_rev_rect = None

    def increment_bucks(self): 
        if self.loop_count % self.buck_rate == 0: 
            self.pizza_bucks += self.buck_booster 
    def draw_bucks(self, game_window):
        if bool(self.bucks_rect): 
            game_window.blit(BACKGROUND, (self.bucks_rect.x, self.bucks_rect.y), self.bucks_rect) 
        bucks_surf = self.display_font.render(str(self.pizza_bucks), True, WHITE) 
        self.bucks_rect = bucks_surf.get_rect() 
        self.bucks_rect.x = WINDOW_WIDTH - 50 
        self.bucks_rect.y = WINDOW_HEIGHT - 50 
        game_window.blit(bucks_surf, self.bucks_rect)
    def draw_bad_reviews(self, game_window): 
        if bool(self.bad_rev_rect): 
            game_window.blit(BACKGROUND, (self.bad_rev_rect.x, 
self.bad_rev_rect.y), self.bad_rev_rect) 
        bad_rev_surf = self.display_font.render(str(self.bad_reviews), True, 
WHITE) 
        self.bad_rev_rect = bad_rev_surf.get_rect() 
        self.bad_rev_rect.x = WINDOW_WIDTH - 150 
        self.bad_rev_rect.y = WINDOW_HEIGHT - 50 
        game_window.blit(bad_rev_surf, self.bad_rev_rect) 
    def draw_timer(self, game_window): 
        if bool(self.timer_rect): 
            game_window.blit(BACKGROUND, 
(self.timer_rect.x,self.timer_rect.y), self.timer_rect) 
        timer_surf = self.display_font.render(str((WIN_TIME - 
self.loop_count) // FRAME_RATE), True, WHITE) 
        self.timer_rect = timer_surf.get_rect() 
        self.timer_rect.x = WINDOW_WIDTH - 250 
        self.timer_rect.y = WINDOW_HEIGHT - 50 
 
 
        game_window.blit(timer_surf, self.timer_rect) 
    def update(self, game_window): 
        self.loop_count += 1 
        self.increment_bucks() 
        self.draw_bucks(game_window) 
        self.draw_bad_reviews(game_window) 
        self.draw_timer(game_window)
        
class Trap(object): 
    def __init__(self, trap_kind, cost, trap_img): 
        self.trap_kind = trap_kind 
        self.cost = cost 
        self.trap_img = trap_img 
 
class TrapApplicator(object): 
    def __init__(self): 
        self.selected = None 
    def select_trap(self, trap): 
        if trap.cost <= counters.pizza_bucks: 
            self.selected = trap 
    def select_tile(self, tile, counters): 
        self.selected = tile.set_trap(self.selected, counters)
        
class BackgroundTile(sprite.Sprite): 
    def __init__(self, rect): 
        super().__init__() 
        self.trap = None
        self.rect = rect
class Trap(object): 
    def __init__(self, trap_kind, cost, trap_img):
        self.trap_kind = trap_kind 
        self.cost = cost 
        self.trap_img = trap_img 
 
class TrapApplicator(object): 
    def __init__(self): 
        self.selected = None 
    def select_trap(self, trap): 
        if trap.cost <= counters.pizza_bucks: 
            self.selected = trap 
    def select_tile(self, tile, counters): 
        self.selected = tile.set_trap(self.selected, counters)
        
class PlayTile(BackgroundTile): 
    def set_trap(self, trap, counters): 
        if bool(trap) and not bool(self.trap): 
            counters.pizza_bucks -= trap.cost 
            self.trap = trap 
            if trap == EARN: 
                counters.buck_booster += 1 
        return None 
    def draw_trap(self, game_window, trap_applicator): 
        if bool(self.trap): 
            game_window.blit(self.trap.trap_img, (self.rect.x, self.rect.y)) 
 
class ButtonTile(BackgroundTile):   
    def set_trap(self, trap, counters): 
        if counters.pizza_bucks >= self.trap.cost: 
            return self.trap 
        else: 
 
 
            return None 
    def draw_trap(self, game_window, trap_applicator): 
        if bool(trap_applicator.selected): 
            if trap_applicator.selected == self.trap: 
                draw.rect(game_window, (238, 190, 47), (self.rect.x, self.rect.y, WIDTH, HEIGHT), 5) 
 
class InactiveTile(BackgroundTile): 
    def set_trap(self, trap, counters): 
        return None 
    def draw_trap(self, game_window, trap_applicator): 
        pass
        
all_vampires = sprite.Group() 

counters = Counters(STARTING_BUCKS, BUCK_RATE, STARTING_BUCK_BOOSTER, WIN_TIME)

SLOW = Trap ('SLOW', 5, GARLIC)
DAMAGE = Trap('DAMAGE', 3, CUTTER)
EARN = Trap('EARN', 7, PEPPERONI)

trap_applicator = TrapApplicator()

 
tile_grid = [] 
 
tile_color = WHITE 
for row in range(6): 
    row_of_tiles = [] 
    tile_grid.append(row_of_tiles) 
    for column in range(11): 
        tile_rect = Rect(WIDTH * column, HEIGHT * row, WIDTH, HEIGHT) 
        if column <= 1: 
            new_tile = InactiveTile(tile_rect) 
        else: 
            if row == 5: 
                if 2<= column <= 4: 
                    new_tile = ButtonTile(tile_rect) 
                    new_tile.trap = [SLOW, DAMAGE, EARN][column - 2] 
                else: 
                    new_tile = InactiveTile(tile_rect) 
            else: 
                new_tile = PlayTile(tile_rect) 
        row_of_tiles.append(new_tile)
        if row == 5 and 2 <= column <=4: 
            BACKGROUND.blit(new_tile.trap.trap_img, (new_tile.rect.x, new_tile.rect.y)) 
        if column != 0 and row != 5: 
            if column != 1: 
                draw.rect(BACKGROUND, tile_color, (WIDTH * column, HEIGHT * 
row, WIDTH, HEIGHT), 1)
GAME_WINDOW.blit(BACKGROUND, (0, 0)) 
 
game_running = True
program_running = True

while game_running: 
     
    for event in pygame.event.get(): 
        if event.type == QUIT: 
            game_running = False 
 
        elif event.type == MOUSEBUTTONDOWN: 
            coordinates = mouse.get_pos() 
            x = coordinates[0] 
            y = coordinates[1] 
            tile_y = y//100 
            tile_x = x//100 
            trap_applicator.select_tile(tile_grid[tile_y][tile_x], counters)
 
    if randint(1, SPAWN_RATE) == 1: 
        VampireSprite()

    for tile_row in tile_grid: 
        for tile in tile_row: 
            if bool(tile.trap): 
                GAME_WINDOW.blit(BACKGROUND, (tile.rect.x, tile.rect.y), tile.rect)
 
    for vampire in all_vampires: 
        tile_row = tile_grid[vampire.rect.y//100] 
        vamp_left_side = vampire.rect.x//100 
        vamp_right_side = (vampire.rect.x+ vampire.rect.width)//100 
        if 0 <= vamp_left_side <= 10: 
            left_tile = tile_row[vamp_left_side] 
        else: 
            left_tile = None 
        if 0 <= vamp_right_side <= 10: 
            right_tile = tile_row[vamp_right_side] 
        else: 
            right_tile = None 
        if bool(left_tile):
            vampire.attack(left_tile)
        if bool(right_tile):
            if right_tile != left_tile:             
                vampire.attack(right_tile)

    if counters.bad_reviews >= MAX_BAD_REVIEWS: 
        game_running = False 
    if counters.loop_count > WIN_TIME: 
        game_running = False
     
    for vampire in all_vampires: 
        vampire.update(GAME_WINDOW, counters)

    for tile_row in tile_grid: 
        for tile in tile_row: 
            tile.draw_trap(GAME_WINDOW, trap_applicator)

    counters.update(GAME_WINDOW)
             
    display.update() 
 
    clock.tick(FRAME_RATE)

end_font = font.Font('pizza_font.ttf',50)  
if program_running: 
    if counters.bad_reviews >= MAX_BAD_REVIEWS: 
        end_surf = end_font.render('you suck', True, WHITE2) 
    else: 
        end_surf = end_font.render('You suck less!', True, WHITE3) 
    GAME_WINDOW.blit(end_surf, (350, 200)) 
    display.update() 
 
while program_running: 
    for event in pygame.event.get(): 
        if event.type == QUIT: 
            program_running = False 
    clock.tick(FRAME_RATE)
    
pygame.quit() 
