Boxhead Recreated With Python With Tkinter
by Hammock Boy in Design > Game Design
11530 Views, 35 Favorites, 0 Comments
Boxhead Recreated With Python With Tkinter
There is a fantastically entertaining computer game called Boxhead, where essentially you and/or a second person fight off hordes of attacking Zombies and Devils with different weapons. For a computer science class this year that I am taking, the final project was to recreate a computer game in Python with Tkinter. Boxhead seemed to be the logical choice and I set about recreating it. I hope you enjoy what it has turned into so far and I hope to add more weapons, level with objects and a second player in the future.
As of now Boxhead can only fight with a pistol and mines, but it would be great to have access to shotgun and rockets.
Feel free to copy the code and play yourself or add weapons. Just keep in mind that the program and images must be kept within the same folder and the images are in sub folders. For example the Boxhead images are within a separate folder than the Zombie images. The Zombies go in the “zombies” sub folder, devils in “devils”, boxhead in “boxhead” and mine/blood/devil attack (yellow sphere) in “game elements”.
The controls for movement are “WASD”, pause “p”, un-pause “o”, switch between weapons “i” and “u”. Most importantly, though, “space” is fire.
If you want to play the game all of the images needed to go along with the code are available here along with the code.
As of now Boxhead can only fight with a pistol and mines, but it would be great to have access to shotgun and rockets.
Feel free to copy the code and play yourself or add weapons. Just keep in mind that the program and images must be kept within the same folder and the images are in sub folders. For example the Boxhead images are within a separate folder than the Zombie images. The Zombies go in the “zombies” sub folder, devils in “devils”, boxhead in “boxhead” and mine/blood/devil attack (yellow sphere) in “game elements”.
The controls for movement are “WASD”, pause “p”, un-pause “o”, switch between weapons “i” and “u”. Most importantly, though, “space” is fire.
If you want to play the game all of the images needed to go along with the code are available here along with the code.
# Boxhead
# By Ben Rothschild
# Boxhead - a copy of the original game made in Python with Tkinter
# Last Edit 12/14/2012
from Tkinter import *
import random
import time
import math
Window_Height = 550 # set the window height and width
Window_Width = 800
X_Window_Buffer = 40
Y_Window_Buffer = 40
canvas = Canvas(highlightthickness=0, height=Window_Height, width=Window_Width)
canvas.master.title("Boxhead")
canvas.pack()
Main = canvas.create_rectangle(0,0,Window_Width,Window_Height,fill="#EBDCC7", belowThis = None) # create the base color similar to that of the Boxhead game
pic = PhotoImage(width=Window_Width, height=Window_Height)
canvas.create_image(0,0,image=pic,anchor=NW)
Zombie_Dict_Made = False # have the Zombies and Boxhead been created?
boxhead_made = False
Run_Game = True
New_Level = False
B_move_length = 2 # Some the game attributes that change and are used for the initial setup. Most would be better in a central Game Class
Zombie_per_move = .5
Devil_move = 1
direction = 1
shot_duration = .01
Zombie_Buffer = 30
kill_zone = 15
Number_of_Zombies = 5
total_devil_attacks = 0
blood_marks = 0
number_of_mines = 0
global pause_game # pause the game if 'P' is pressed or start it up if 'O' is pressed
pause_game = False
Mines_Dict = {} # holds all of the mines
Zombie_Dict = {} # Where the Zombies are kept - elements are deleted as Boxhead shoots them
Devil_Dict = {} # same as Zombie_Dict but for Devils
Dead_Zombie_List = []
Devil_Attack_Dict = {} # The spheres that the Devils can attack with
class Edge_limits(object):
"""Tells limits in x any y direction to objects so that they don't run off of the game screen"""
def __init__(self):
self.x_start = 2*X_Window_Buffer - 20
self.y_start = 3*Y_Window_Buffer -35
self.x_end = Window_Width - X_Window_Buffer - 20
self.y_end = Window_Height - Y_Window_Buffer - 20
class Buffer(object):
"""The edge buffers for the game"""
def __init__ (self,x_start,y_start,x_end,y_end,fill):
canvas.create_rectangle(x_start,y_start,x_end,y_end,fill = fill)
left_buffer = Buffer(0,0,(X_Window_Buffer),(Y_Window_Buffer+Window_Height), "Black") # create all of the buffer images
right_buffer = Buffer((X_Window_Buffer+Window_Width),0,(Window_Width-(X_Window_Buffer)),((2*Y_Window_Buffer)+Window_Height), "Black")
top_buffer = Buffer(0,0,(Window_Width-X_Window_Buffer),Y_Window_Buffer,"Black")
bottom_buffer = Buffer(0,(Window_Height-Y_Window_Buffer),Window_Width,Window_Height,"Black")
class Blood(object):
"""What happens when you kill something. It create a blood spot on the coordinates of the killed Zombie(s) / Devil(s)
They are deleted at the beginning of each new level"""
def __init__(self,x,y):
global base_for_blood
self.image = PhotoImage(file = "images/game_elements/blood.gif")
self.blood_spot = canvas.create_image(x,y,image = self.image)
canvas.tag_lower(self.blood_spot)
canvas.tag_lower(Main)
class MINE(object):
""" The mines class. Watch where you step"""
def __init__(self,x,y):
self.photo = PhotoImage(file = "images/game_elements/mine.gif")
self.image = canvas.create_image(x,y,image = self.photo) # Create a black rectangle for the mine image
canvas.tag_lower(self.image)
canvas.tag_lower(Main)
self.destroy = False
self.x = x
self.y = y
def explode(self):
"""Determine if a Zombie or Devil is close enought to set of the mine. If that is True then it tests
to see whether any Zombie or Devil in the greater surrounding area should be killed"""
destroy_zombie = []
destroy_devil = []
self.exploded = False
for the_zombie in Zombie_Dict:
Zombie = Zombie_Dict[the_zombie]
if abs(self.x - Zombie.x) < 20 and abs(self.y - Zombie.y) < 20: # Test to see if an Zombie/Devil is within the box that is +/- 40 pixels of the mine's x and y
self.exploded = True
self.destroy = True
for the_devil in Devil_Dict:
Devil = Devil_Dict[the_devil]
if abs(self.x - Devil.x) < 20 and abs(self.y - Devil.y) < 20:
self.exploded = True
self.destroy = True
if self.exploded == True:
explode = canvas.create_oval((self.x - 80),(self.y - 80),(self.x + 80),(self.y + 80),fill='Orange') # the Radius of the explosion is 80
canvas.update()
if self.exploded == True:
for devil in Devil_Dict:
Devil = Devil_Dict[devil]# Add the Zombie to a list to be deleted, since you cannot modify Dictionaries while traversing them
if abs(self.x - Devil.x) < 80 and abs(self.y - Devil.y) < 80:
destroy_devil.append(devil)
for zombie in Zombie_Dict:
Zombie = Zombie_Dict[zombie]
if abs(self.x - Zombie.x) < 80 and abs(self.y - Zombie.y) < 80:
destroy_zombie.append(zombie)
for item in destroy_zombie: # Delete the Zombie/Devils caught up in the explosion
canvas.delete(Zombie_Dict[item].zombie)
del Zombie_Dict[item]
for item in destroy_devil:
canvas.delete(Devil_Dict[item].devil)
del Devil_Dict[item]
if self.exploded == True:
canvas.delete(explode)
class Zombie_Attack(object):
"""The yellow circle that the zombies uses to attack Boxhead. It has a life span of 125 instances in the while loop before it disappears.
Unless of course it strikes boxhead and lowers boxhead's health by a lot"""
def __init__(self,x,y,x_vel,y_vel):
self.x = x
self.y = y
self.image = PhotoImage(file = "images/game_elements/devil_a.gif")
self.attack = canvas.create_image(self.x,self.y,image = self.image)
self.x_vel = x_vel
if self.x_vel > 0: # If the velocity in that direction is not 0 it adds 1 to the speed so that it is faster than the Devil who shot it.
self.x_vel += .75
if self.x_vel < 0:
self.x_vel -= .75
self.y_vel = y_vel
if self.y_vel > 0:
self.y_vel += .75
if self.y_vel < 0:
self.y_vel -= .75
self.life_span = 125
def move(self):
global boxhead1
self.x += self.x_vel
self.y += self.y_vel
canvas.coords(self.attack,self.x,self.y)
self.life_span -=1
if abs(self.x - boxhead1.x) < 30 and abs(self.y - boxhead1.y) < 30: #Strike Boxhead if within 30 pixels
boxhead1.health -= 10
self.life_span = 0
class Shot(object):
"""Correct where gun shoots from depending on which direction boxhead is. Because of the Boxhead image the coordinates from where the gun is if Boxhead is shooting up
is different that if he were shooting to the left in regards to the original x,y position in the top left of the image"""
class Stats(object):
"""Creates the score label/info. This updates once per loop based on all of Boxhead's attributes ex. health and score"""
def __init__(self):
global boxhead1
self.board = self.board = canvas.create_text(200,65)
canvas.create_rectangle(X_Window_Buffer,Y_Window_Buffer,Window_Width-X_Window_Buffer,Y_Window_Buffer+20,fill="Red")
def update(self):
health_string = str(boxhead1.health)
score_string = str(boxhead1.score)
level_string = str(boxhead1.level)
gun_string = str(boxhead1.gun)
ammo_string = str(boxhead1.ammo)
score_board = "Health: " + health_string + " " + "Score: " + score_string + " " + "Level: " + level_string + " " + "Gun: " + gun_string + " " + "Ammo: " + ammo_string
canvas.delete(self.board)
self.board = canvas.create_text(230,52,text=score_board)
class Boxhead(object):
"""The Boxhead charecter. Shoot, move, lay mines etc. are all contianed within the Boxhead class. Eventually all of the gun details need to be moved to thier own class so that Pistol = Gun(range,damage) and Mine = Gun(radius, damage)
eventually even Shotgun = Gun(range,damange,arc_width) and so on"""
def __init__(self):
self.image_up = PhotoImage(file = "images/boxhead/bhup.gif") # The image changes if Boxhead is facing up down left right
self.image_down = PhotoImage(file = "images/boxhead/bhdown.gif")
self.image_left = PhotoImage(file = "images/boxhead/bhleft.gif")
self.image_right = PhotoImage(file = "images/boxhead/bhright.gif")
self.x = random.randrange(((game_limit.x_start/2)+15),game_limit.x_end) # pick a random starting point on the right side of the field. Zombies start on the left half.
self.y = random.randrange(game_limit.y_start,game_limit.y_end)
self.image = canvas.create_image(self.x,self.y,image = self.image_up)
self.x_vel = 0
self.y_vel = 0
self.direction = 1
self.health = 100 # +5 health is added at the beginning of every level
self.gun = "Pistol"
self.level = 1
self.score = 0
self.ammo = "Infinite"
self.pause = False
self.bonus_score = 0
self.pistol_range = 150 # the range of the pistol in pixels
self.mine_count = 0 # how many mines are left
def move(self):
global move
if (self.x >= game_limit.x_end) and self.x_vel > 0: # Can boxhead move in that direction or will he strike the edge of the game
self.x_vel = 0
if self.x <= game_limit.x_start and self.x_vel < 0:
self.x_vel = 0
else:
pass
if (self.y >= game_limit.y_end) and self.y_vel > 0:
self.y_vel = 0
elif self.y <= game_limit.y_start and self.y_vel < 0:
self.y_vel = 0
else:
pass
self.x += self.x_vel
self.y += self.y_vel
canvas.coords(self.image,(self.x),(self.y))
def shot_coords_update(self):
"""update the coordinates of where the gun should be fired from"""
if self.gun == "Pistol" or self.gun == 'Mines':
gun_range = self.pistol_range
global up
global down
global left
global right
up.x_start = 10 + boxhead1.x
up.y_start = -5 + boxhead1.y
up.x_end = 11 + boxhead1.x
up.y_end = boxhead1.y - (gun_range + 5)
down.x_start = boxhead1.x - 10
down.y_start = 5 + boxhead1.y
down.x_end = boxhead1.x - 9
down.y_end = gun_range+5 + boxhead1.y
left.x_start = 15 + boxhead1.x
left.y_start = boxhead1.y - 15
left.x_end = boxhead1.x - gun_range - 15
left.y_end = boxhead1.y -15
right.x_start = 5 + boxhead1.x
right.y_start = 0 + boxhead1.y
right.x_end = gun_range + 5 + boxhead1.x
right.y_end = 1 + boxhead1.y
if self.direction == 1: # what direction boxhead is fact 1=up 2=down etc.
boxhead1.shoot_coords(up.x_start,up.y_start,up.x_end,up.y_end)
if self.direction == 2:
boxhead1.shoot_coords(down.x_start,down.y_start,down.x_end,down.y_end)
if self.direction == 3:
boxhead1.shoot_coords(left.x_start,left.y_start,left.x_end,left.y_end)
if self.direction == 4:
boxhead1.shoot_coords(right.x_start,right.y_start,right.x_end,right.y_end)
def pic(self):
"""Change Boxhead's image based on the direction he is moving"""
if self.direction == 1:
canvas.itemconfigure(self.image, image = self.image_up)
if self.direction == 2:
canvas.itemconfigure(self.image, image = self.image_down)
if self.direction == 3:
canvas.itemconfigure(self.image, image = self.image_left)
if self.direction == 4:
canvas.itemconfigure(self.image, image = self.image_right)
def fire_gun(self):
"""Fires whichever weapon that boxhead is using at the moment"""
global blood_marks,Blood_Dict
self.bonus_score = 0
Dead_Zombie_List = []
which_zombie = 0
global Zombie_Dict
kill_list = [] # the librarys that hold which Zombie needs to be deleted from Zombie_Dict
kill_devil = []
if self.gun == "Pistol":
self.bullet_image = canvas.create_rectangle(self.shoot_x_start,self.shoot_y_start,self.shoot_x_end+1,self.shoot_y_end+1,fill="Black") # create the bullet
canvas.update()
for Each_Zombie in Zombie_Dict:
Zombie = Zombie_Dict[Each_Zombie] # test whether every Zombie is within the path of the bullet
if self.direction == 1:
if Zombie.y < self.shoot_y_start and Zombie.y > self.shoot_y_end and abs(Zombie.x - self.shoot_x_start) < 25:
kill_list.append(Each_Zombie)
elif self.direction == 2:
if Zombie.y > self.shoot_y_start and Zombie.y < self.shoot_y_end and abs(Zombie.x - self.shoot_x_start) < 25:
kill_list.append(Each_Zombie)
elif self.direction == 3:
if Zombie.x < self.shoot_x_start and Zombie.x > self.shoot_x_end and abs(Zombie.y - self.shoot_y_start) < 25:
kill_list.append(Each_Zombie)
elif self.direction == 4:
if Zombie.x > self.shoot_x_start and Zombie.x < self.shoot_x_end and abs(Zombie.y - self.shoot_y_start) < 25:
kill_list.append(Each_Zombie)
for each_devil in Devil_Dict:
Zombie = Devil_Dict[each_devil]
if self.direction == 1:
if Zombie.y < self.shoot_y_start and Zombie.y > self.shoot_y_end and abs(Zombie.x - self.shoot_x_start) < 25:
Zombie.health -= 26 # Lower the Devil's health by 26 so that it takes 4 shots to kill a Devil while 1 for a Zombie
kill_devil.append(each_devil)
elif self.direction == 2:
if Zombie.y > self.shoot_y_start and Zombie.y < self.shoot_y_end and abs(Zombie.x - self.shoot_x_start) < 25:
Zombie.health -= 26
kill_devil.append(each_devil)
elif self.direction == 3:
if Zombie.x < self.shoot_x_start and Zombie.x > self.shoot_x_end and abs(Zombie.y - self.shoot_y_start) < 25:
Zombie.health -= 26
kill_devil.append(each_devil)
elif self.direction == 4:
if Zombie.x > self.shoot_x_start and Zombie.x < self.shoot_x_end and abs(Zombie.y - self.shoot_y_start) < 25:
Zombie.health -= 26
kill_devil.append(each_devil)
for Each_Zombie in kill_list: # Destroy the Zombie to be killed from the Zombie_Dict and canvas
mark = Blood(Zombie_Dict[Each_Zombie].x,Zombie_Dict[Each_Zombie].y)
Blood_Dict[blood_marks] = mark
blood_marks +=1
canvas.delete(Zombie_Dict[Each_Zombie])
del Zombie_Dict[Each_Zombie]
boxhead1.score+=1
self.bonus_score +=1
for the_devil in kill_devil:
mark = Blood(Devil_Dict[the_devil].x,Devil_Dict[the_devil].y)
Blood_Dict[blood_marks] = mark
blood_marks +=1
if Devil_Dict[the_devil].health <= 0:
canvas.delete(Devil_Dict[the_devil])
del Devil_Dict[the_devil]
boxhead1.score+=1
self.bonus_score +=1
canvas.delete(self.bullet_image)
self.score += (self.bonus_score / 3)
if self.gun == 'Mines': # lay a mine and give it mine.x = boxhead1.x and mine.y = boxhead1.y
global number_of_mines
if self.mine_count > 0:
mine = MINE(self.x,self.y)
Mines_Dict[number_of_mines] = mine
number_of_mines +=1
self.mine_count -=1
else:
pass
canvas.update()
def key(self,key):
"""Look at the input from the keyboard and adjust Boxhead accordingly. Movement = WASD Fire = Space Pistol = I Mines = U Pause = P Unpause = O"""
global press,pause_game
press = key
if press == 'w':
self.x_vel = 0
self.y_vel = -B_move_length
self.direction = 1
if press == 's':
self.x_vel = 0
self.y_vel = B_move_length
self.direction = 2
if press == 'a':
self.x_vel = -B_move_length
self.y_vel = 0
self.direction = 3
if press == 'd':
self.x_vel = B_move_length
self.y_vel = 0
self.direction = 4
if press == 'space':
self.fire_gun()
if press == 'p':
pause_game = True
if press == 'o':
pause_game = False
if press == 'i':
self.gun = "Pistol"
self.ammo = 'Infinte'
if press == 'u':
self.gun = 'Mines'
self.ammo = self.mine_count
def shoot_coords(self,x_start,y_start,x_end,y_end):
"""Help to adjust the coordinates based on where to shoot from each direction"""
self.shoot_x_start = x_start
self.shoot_y_start = y_start
self.shoot_x_end = x_end
self.shoot_y_end = y_end
class Zombie(object):
"""ZOMBIES. Nothing like a bunch of Zombies that chase you around. Boxhead is faster then Zombies, but Zombies can move diagonally"""
def __init__(self):
self.zup = PhotoImage(file = "images/zombies/zup.gif") # there are 8 directions that Zombies can move in
self.zdown = PhotoImage(file = "images/zombies/zdown.gif")
self.zleft = PhotoImage(file = "images/zombies/zleft.gif")
self.zright = PhotoImage(file = "images/zombies/zright.gif")
self.zrightup = PhotoImage(file = "images/zombies/zrightup.gif")
self.zrightdown = PhotoImage(file = "images/zombies/zrightdown.gif")
self.zleftup = PhotoImage(file = "images/zombies/zleftup.gif")
self.zleftdown = PhotoImage(file = "images/zombies/zleftdown.gif")
self.x = random.randrange(game_limit.x_start,(game_limit.x_end-(game_limit.x_end / 2))) # create Zombies in the left half of the arena
self.y = random.randrange(game_limit.y_start,game_limit.y_end)
self.direction = 1
self.zombie = canvas.create_image(self.x,self.y, image = self.zup)
self.alive = True
self.distance_to_b = 0
self.attacked = False
def move(self,target):
"""This function like Boxhead1.move tests to see whether the Zombie will hit the edge of the game, but also tests to see whether the Zombie will collide with another
Zombie in front of it. This helps avoid having all of the Zombies stack up on top of each other and froming one really dense Zombie. That is what the really long line of code
below is testing"""
global boxhead1
which_zombie = 0
collision = False
self.x_vel = 0
self.y_vel = 0
for which_zombie in Zombie_Dict:
test_self = Zombie_Dict[which_zombie]
if abs(self.x - boxhead1.x) - abs(boxhead1.x - test_self.x) > 0 and abs(self.x - boxhead1.x) - abs(boxhead1.x - test_self.x) < Zombie_Buffer and abs(self.y - boxhead1.y) - abs(boxhead1.y - test_self.y) > 0 and abs(self.y - boxhead1.y) - abs(boxhead1.y - test_self.y) < Zombie_Buffer:
collision = True
else:
pass
if collision == True:
pass
elif collision == False:
if self.x < target.x:
self.x_vel = Zombie_per_move
if self.x > target.x:
self.x_vel= -Zombie_per_move
elif self.x == target.x:
self.x_vel = 0
if self.x >= Window_Width - 25: # x coords
self.x_vel = -Zombie_per_move
if self.x <= 0 + 5:
self.x_vel = Zombie_per_move
if self.y < target.y:
self.y_vel = Zombie_per_move
if self.y > target.y:
self.y_vel = -Zombie_per_move
elif self.y == target.y:
self.y_vel = 0
if self.y >= Window_Height - 25:# y coords
self.y_vel = -Zombie_per_move
if self.y <= 0 + 5:
self.y_vel = Zombie_per_move
self.y += self.y_vel
self.x += self.x_vel
canvas.coords(self.zombie,(self.x),(self.y)) # move the Zombie accordingly based on if it should move or another Zombie is in its path
else:
pass
def pic(self):
"""Update the Zombie image based on which of the 8 directions that it is traveling in"""
if self.y_vel < 0 and self.x_vel == 0:
canvas.itemconfigure(self.zombie, image = self.zup)
if self.y_vel > 0 and self.x_vel == 0:
canvas.itemconfigure(self.zombie, image = self.zdown)
if self.x_vel < 0 and self.y_vel == 0:
canvas.itemconfigure(self.zombie, image = self.zleft)
if self.x_vel > 0 and self.y_vel == 0:
canvas.itemconfigure(self.zombie, image = self.zright)
if self.y_vel > 0 and self.x_vel > 0:
canvas.itemconfigure(self.zombie, image = self.zrightdown)
if self.y_vel < 0 and self.x_vel > 0:
canvas.itemconfigure(self.zombie, image = self.zrightup)
if self.y_vel > 0 and self.x_vel < 0:
canvas.itemconfigure(self.zombie, image = self.zleftdown)
if self.y_vel < 0 and self.x_vel < 0:
canvas.itemconfigure(self.zombie, image = self.zleftup)
def contact(self):
"""This is how the Zombies do damage to Boxhead. If they com in contact with Boxhead it deducts health from boxhead"""
if abs(boxhead1.x - self.x) < 10 and abs(boxhead1.y - self.y) < 10 and self.attacked == False:
boxhead1.health -= 1
self.attacked = True
else:
self.attacked = False
class Devil(object):
"""The Devil Class. They move faster than Zombies have more health and can attack Boxhead by colliding with him or by shooting him"""
def __init__(self):
self.x = random.randrange(game_limit.x_start,(game_limit.x_end-(game_limit.x_end / 2)))
self.y = random.randrange(game_limit.y_start,game_limit.y_end)
self.direction = 1
self.alive = True
self.distance_to_b = 0
self.attacked = False
self.attack_fire = 0
self.health = 100
self.dup = PhotoImage(file = "images/devils/du.gif") # the 8 Devil images
self.ddown = PhotoImage(file = "images/devils/db.gif")
self.dleft = PhotoImage(file = "images/devils/dl.gif")
self.dright = PhotoImage(file = "images/devils/dr.gif")
self.drightup = PhotoImage(file = "images/devils/dtr.gif")
self.drightdown = PhotoImage(file = "images/devils/dbr.gif")
self.dleftup = PhotoImage(file = "images/devils/dtl.gif")
self.dleftdown = PhotoImage(file = "images/devils/dbl.gif")
self.devil = canvas.create_image(self.x,self.y, image = self.dup)
def move(self,target):
"""The Devil's movement is the same as the Zombies except that Devils move faster"""
which_zombie = 0
collision = False
self.x_vel = 0
self.y_vel = 0
for the_devil in Devil_Dict:
test_self = Devil_Dict[the_devil]
if abs(self.x - boxhead1.x) - abs(boxhead1.x - test_self.x) > 0 and abs(self.x - boxhead1.x) - abs(boxhead1.x - test_self.x) < Zombie_Buffer and abs(self.y - boxhead1.y) - abs(boxhead1.y - test_self.y) > 0 and abs(self.y - boxhead1.y) - abs(boxhead1.y - test_self.y) < Zombie_Buffer:
collision = True
else:
pass
if collision == True:
pass
elif collision == False:
if self.x < target.x:
self.x_vel = Devil_move
if self.x > target.x:
self.x_vel= -Devil_move
elif self.x == target.x:
self.x_vel = 0
if self.x >= Window_Width - 25: # x coords
self.x_vel = -Devil_move
if self.x <= 0 + 5:
self.x_vel = Devil_move
if self.y < target.y:
self.y_vel = Devil_move
if self.y > target.y:
self.y_vel = -Devil_move
elif self.y == target.y:
self.y_vel = 0
if self.y >= Window_Height - 25:# y coords
self.y_vel = -Devil_move
if self.y <= 0 + 5:
self.y_vel = Devil_move
self.y += self.y_vel
self.x += self.x_vel
canvas.coords(self.devil,(self.x),(self.y))
else:
pass
def pic(self):
"""update the image"""
if self.y_vel < 0 and self.x_vel == 0:
canvas.itemconfigure(self.devil, image = self.dup)
if self.y_vel > 0 and self.x_vel == 0:
canvas.itemconfigure(self.devil, image = self.ddown)
if self.x_vel < 0 and self.y_vel == 0:
canvas.itemconfigure(self.devil, image = self.dleft)
if self.x_vel > 0 and self.y_vel == 0:
canvas.itemconfigure(self.devil, image = self.dright)
if self.y_vel > 0 and self.x_vel > 0:
canvas.itemconfigure(self.devil, image = self.drightdown)
if self.y_vel < 0 and self.x_vel > 0:
canvas.itemconfigure(self.devil, image = self.drightup)
if self.y_vel > 0 and self.x_vel < 0:
canvas.itemconfigure(self.devil, image = self.dleftdown)
if self.y_vel < 0 and self.x_vel < 0:
canvas.itemconfigure(self.devil, image = self.dleftup)
def contact(self):
"""If a Devil comes in contact with boxhead it deducts more health than a Zombie would"""
if abs(boxhead1.x - self.x) < 10 and abs(boxhead1.y - self.y) < 10 and self.attacked == False:
boxhead1.health -= 2
self.attacked = True
else:
self.attacked = False
def attack(self,boxhead1):
"""If the Devil is within +/- 200 pixels in the X and Y directions then it shoots a fireball at boxhead 1 time and then waits 45 loops to shoot agian"""
global total_devil_attacks
if abs(boxhead1.x - self.x) < 200 and abs(boxhead1.y - self.y) < 200 and self.attack_fire > 45:
d_attack = Zombie_Attack(self.x,self.y,self.x_vel,self.y_vel)
Devil_Attack_Dict[total_devil_attacks] = d_attack
total_devil_attacks +=1
self.attack_fire = 0
else:
self.attack_fire +=1
def key_press(event):
"""This function passes all of the key presses to the Boxhead1.key function for further analysis"""
global pause_game
press = event.keysym
boxhead1.key(press)
if press == 'o':
pause_game = False
def init_game_parts():
""" This builds all of the inital game elements that are only created once regardless of the number of levels. For example it creates the score board"""
global up, down, right, left
global down
global right
global left
global current_shot
global game_limit
global score_board
global boxhead1
global Zombie_Dict
global game_limit
up = Shot()
down = Shot()
left = Shot()
right = Shot()
current_shot = Shot()
game_limit = Edge_limits()
boxhead1 = Boxhead()
score_board = Stats()
def new_level():
"""For every new level all of the Devils and Zombies have been killed so new ones need to be created. Each time 70% more Zombies are added"""
build_zombie = 0
build_devil = 0
for i in range(Number_of_Zombies):
z = Zombie()
Zombie_Dict[build_zombie] = z
build_zombie+=1
for i in range(int(Number_of_Zombies / 5)):
D = Devil()
Devil_Dict[build_devil] = D
build_devil +=1
def main_loop():
"""The central function for the game. There are 2 while loops. The inner one is only broken for a new level and the outer while loop is only broken
if boxhead dies and the game is over"""
global New_Level,Run_Game,Zombie_Dict,Dead_Zombie_List,Number_of_Zombies,boxhead1
init_game_parts() # create all of the game images like the edge buffers
while Run_Game == True:
global Blood_Dict
Blood_Dict = {} # create a new empty blood dictionary
if boxhead1.health <= 0: # boxhead died - game over
return 'Game Over! Final Score: '+str(boxhead1.score)+' Final Level: '+str((boxhead1.level - 1))
else:
new_level()
boxhead1.health += 5 # add +5 to Boxheads health each new level
boxhead1.mine_count += int(Number_of_Zombies / 5) # Boxhead gets 1/5 of the # of Zombies of Mines. If there are 5 Zombies Boxhead gets 1 mine
while New_Level == False: # the Level loop that runs until Boxhead dies or all of the Zombie/Devils have been killed
New_Level = False
"""Moves the Devils and Zombies"""
for the_zombie in Zombie_Dict:
if pause_game != True:
Zombie_Dict[the_zombie].move(boxhead1)
Zombie_Dict[the_zombie].pic()
Zombie_Dict[the_zombie].contact()
for the_devil in Devil_Dict:
if pause_game != True:
Devil_Dict[the_devil].move(boxhead1)
Devil_Dict[the_devil].attack(boxhead1)
Devil_Dict[the_devil].pic()
Devil_Dict[the_devil].contact()
destroy = []
""" The attack sphere that the Devils shoot"""
if pause_game != True:
for d_attack in Devil_Attack_Dict:
Devil_Attack_Dict[d_attack].move()
if Devil_Attack_Dict[d_attack].life_span <= 0:
destroy.append(d_attack)
for item in destroy:
canvas.delete(Devil_Attack_Dict[item].attack)
del Devil_Attack_Dict[item]
"""Explode the mines"""
mine_destroy = []
for mine in Mines_Dict:
Mines_Dict[mine].explode()
if Mines_Dict[mine].destroy == True:
mine_destroy.append(mine)
for mine in mine_destroy:
canvas.delete(Mines_Dict[mine].image)
del Mines_Dict[mine]
"""Boxhead moves"""
if pause_game != True:
boxhead1.move()
boxhead1.pic()
boxhead1.shot_coords_update()
score_board.update()
time.sleep(.02) # sleep for 1/100 of a second between loops
canvas.update()
if len(Zombie_Dict) == 0 and len(Devil_Dict) == 0: # if they both = 0 then a new level is created
New_Level = True
if boxhead1.health <= 0:
New_Level = True
Run_Game = False
boxhead1.level +=1
Number_of_Zombies = int(float(Number_of_Zombies) * 1.7) # Increase the number of Zombies each round
for blood in Blood_Dict: # Delete all of the blood for the new round
canvas.delete(Blood_Dict[blood])
New_Level = False
print 'Game Over! Final Score: '+str(boxhead1.score)+' Final Level: '+str(boxhead1.level - 1) # print the final score
canvas.after(30, main_loop)
canvas.master.bind("", key_press)
canvas.pack()
canvas.mainloop()