parent
58bc70c436
commit
4ca4e3d936
Binary file not shown.
@ -1 +0,0 @@
|
||||
Subproject commit afc4ae12c7a19bee5aaa2c20e9d765e1afcccd80
|
@ -1,6 +0,0 @@
|
||||
import pygame as pg
|
||||
from source.main import main
|
||||
|
||||
if __name__=='__main__':
|
||||
main()
|
||||
pg.quit()
|
@ -1,45 +0,0 @@
|
||||
__author__ = 'marble_xu'
|
||||
|
||||
import random
|
||||
import pygame as pg
|
||||
from .. import tool
|
||||
from .. import constants as c
|
||||
|
||||
class Map():
|
||||
def __init__(self, width, height):
|
||||
self.width = width
|
||||
self.height = height
|
||||
self.map = [[0 for x in range(self.width)] for y in range(self.height)]
|
||||
|
||||
def isValid(self, map_x, map_y):
|
||||
if (map_x < 0 or map_x >= self.width or
|
||||
map_y < 0 or map_y >= self.height):
|
||||
return False
|
||||
return True
|
||||
|
||||
def isMovable(self, map_x, map_y):
|
||||
return (self.map[map_y][map_x] == c.MAP_EMPTY)
|
||||
|
||||
def getMapIndex(self, x, y):
|
||||
x -= c.MAP_OFFSET_X
|
||||
y -= c.MAP_OFFSET_Y
|
||||
return (x // c.GRID_X_SIZE, y // c.GRID_Y_SIZE)
|
||||
|
||||
def getMapGridPos(self, map_x, map_y):
|
||||
return (map_x * c.GRID_X_SIZE + c.GRID_X_SIZE//2 + c.MAP_OFFSET_X,
|
||||
map_y * c.GRID_Y_SIZE + c.GRID_Y_SIZE//5 * 3 + c.MAP_OFFSET_Y)
|
||||
|
||||
def setMapGridType(self, map_x, map_y, type):
|
||||
self.map[map_y][map_x] = type
|
||||
|
||||
def getRandomMapIndex(self):
|
||||
map_x = random.randint(0, self.width-1)
|
||||
map_y = random.randint(0, self.height-1)
|
||||
return (map_x, map_y)
|
||||
|
||||
def showPlant(self, x, y):
|
||||
pos = None
|
||||
map_x, map_y = self.getMapIndex(x, y)
|
||||
if self.isValid(map_x, map_y) and self.isMovable(map_x, map_y):
|
||||
pos = self.getMapGridPos(map_x, map_y)
|
||||
return pos
|
@ -1,441 +0,0 @@
|
||||
__author__ = 'marble_xu'
|
||||
|
||||
import random
|
||||
import pygame as pg
|
||||
from .. import tool
|
||||
from .. import constants as c
|
||||
|
||||
PANEL_Y_START = 87
|
||||
PANEL_X_START = 22
|
||||
PANEL_Y_INTERNAL = 74
|
||||
PANEL_X_INTERNAL = 53
|
||||
CARD_LIST_NUM = 8
|
||||
|
||||
card_name_list = [c.CARD_SUNFLOWER, c.CARD_PEASHOOTER, c.CARD_SNOWPEASHOOTER, c.CARD_WALLNUT,
|
||||
c.CARD_CHERRYBOMB, c.CARD_THREEPEASHOOTER, c.CARD_REPEATERPEA, c.CARD_CHOMPER,
|
||||
c.CARD_PUFFSHROOM, c.CARD_POTATOMINE, c.CARD_SQUASH, c.CARD_SPIKEWEED,
|
||||
c.CARD_JALAPENO, c.CARD_SCAREDYSHROOM, c.CARD_SUNSHROOM, c.CARD_ICESHROOM,
|
||||
c.CARD_HYPNOSHROOM, c.CARD_WALLNUT, c.CARD_REDWALLNUT]
|
||||
plant_name_list = [c.SUNFLOWER, c.PEASHOOTER, c.SNOWPEASHOOTER, c.WALLNUT,
|
||||
c.CHERRYBOMB, c.THREEPEASHOOTER, c.REPEATERPEA, c.CHOMPER,
|
||||
c.PUFFSHROOM, c.POTATOMINE, c.SQUASH, c.SPIKEWEED,
|
||||
c.JALAPENO, c.SCAREDYSHROOM, c.SUNSHROOM, c.ICESHROOM,
|
||||
c.HYPNOSHROOM, c.WALLNUTBOWLING, c.REDWALLNUTBOWLING]
|
||||
plant_sun_list = [50, 100, 175, 50, 150, 325, 200, 150, 0, 25, 50, 100, 125, 25, 25, 75, 75, 0, 0]
|
||||
plant_frozen_time_list = [7500, 7500, 7500, 30000, 50000, 7500, 7500, 7500, 7500, 30000,
|
||||
30000, 7500, 50000, 7500, 7500, 50000, 30000, 0, 0]
|
||||
all_card_list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
|
||||
|
||||
def getSunValueImage(sun_value):
|
||||
font = pg.font.SysFont(None, 22)
|
||||
width = 32
|
||||
msg_image = font.render(str(sun_value), True, c.NAVYBLUE, c.LIGHTYELLOW)
|
||||
msg_rect = msg_image.get_rect()
|
||||
msg_w = msg_rect.width
|
||||
|
||||
image = pg.Surface([width, 17])
|
||||
x = width - msg_w
|
||||
|
||||
image.fill(c.LIGHTYELLOW)
|
||||
image.blit(msg_image, (x, 0), (0, 0, msg_rect.w, msg_rect.h))
|
||||
image.set_colorkey(c.BLACK)
|
||||
return image
|
||||
|
||||
def getCardPool(data):
|
||||
card_pool = []
|
||||
for card in data:
|
||||
tmp = card['name']
|
||||
for i,name in enumerate(plant_name_list):
|
||||
if name == tmp:
|
||||
card_pool.append(i)
|
||||
break
|
||||
return card_pool
|
||||
|
||||
class Card():
|
||||
def __init__(self, x, y, name_index, scale=0.78):
|
||||
self.loadFrame(card_name_list[name_index], scale)
|
||||
self.rect = self.orig_image.get_rect()
|
||||
self.rect.x = x
|
||||
self.rect.y = y
|
||||
|
||||
self.name_index = name_index
|
||||
self.sun_cost = plant_sun_list[name_index]
|
||||
self.frozen_time = plant_frozen_time_list[name_index]
|
||||
self.frozen_timer = -self.frozen_time
|
||||
self.refresh_timer = 0
|
||||
self.select = True
|
||||
|
||||
def loadFrame(self, name, scale):
|
||||
frame = tool.GFX[name]
|
||||
rect = frame.get_rect()
|
||||
width, height = rect.w, rect.h
|
||||
|
||||
self.orig_image = tool.get_image(frame, 0, 0, width, height, c.BLACK, scale)
|
||||
self.image = self.orig_image
|
||||
|
||||
def checkMouseClick(self, mouse_pos):
|
||||
x, y = mouse_pos
|
||||
if(x >= self.rect.x and x <= self.rect.right and
|
||||
y >= self.rect.y and y <= self.rect.bottom):
|
||||
return True
|
||||
return False
|
||||
|
||||
def canClick(self, sun_value, current_time):
|
||||
if self.sun_cost <= sun_value and (current_time - self.frozen_timer) > self.frozen_time:
|
||||
return True
|
||||
return False
|
||||
|
||||
def canSelect(self):
|
||||
return self.select
|
||||
|
||||
def setSelect(self, can_select):
|
||||
self.select = can_select
|
||||
if can_select:
|
||||
self.image.set_alpha(255)
|
||||
else:
|
||||
self.image.set_alpha(128)
|
||||
|
||||
def setFrozenTime(self, current_time):
|
||||
self.frozen_timer = current_time
|
||||
|
||||
def createShowImage(self, sun_value, current_time):
|
||||
'''create a card image to show cool down status
|
||||
or disable status when have not enough sun value'''
|
||||
time = current_time - self.frozen_timer
|
||||
if time < self.frozen_time: #cool down status
|
||||
image = pg.Surface([self.rect.w, self.rect.h])
|
||||
frozen_image = self.orig_image.copy()
|
||||
frozen_image.set_alpha(128)
|
||||
frozen_height = (self.frozen_time - time)/self.frozen_time * self.rect.h
|
||||
|
||||
image.blit(frozen_image, (0,0), (0, 0, self.rect.w, frozen_height))
|
||||
image.blit(self.orig_image, (0,frozen_height),
|
||||
(0, frozen_height, self.rect.w, self.rect.h - frozen_height))
|
||||
elif self.sun_cost > sun_value: #disable status
|
||||
image = self.orig_image.copy()
|
||||
image.set_alpha(192)
|
||||
else:
|
||||
image = self.orig_image
|
||||
return image
|
||||
|
||||
def update(self, sun_value, current_time):
|
||||
if (current_time - self.refresh_timer) >= 250:
|
||||
self.image = self.createShowImage(sun_value, current_time)
|
||||
self.refresh_timer = current_time
|
||||
|
||||
def draw(self, surface):
|
||||
surface.blit(self.image, self.rect)
|
||||
|
||||
class MenuBar():
|
||||
def __init__(self, card_list, sun_value):
|
||||
self.loadFrame(c.MENUBAR_BACKGROUND)
|
||||
self.rect = self.image.get_rect()
|
||||
self.rect.x = 10
|
||||
self.rect.y = 0
|
||||
|
||||
self.sun_value = sun_value
|
||||
self.card_offset_x = 32
|
||||
self.setupCards(card_list)
|
||||
|
||||
def loadFrame(self, name):
|
||||
frame = tool.GFX[name]
|
||||
rect = frame.get_rect()
|
||||
frame_rect = (rect.x, rect.y, rect.w, rect.h)
|
||||
|
||||
self.image = tool.get_image(tool.GFX[name], *frame_rect, c.WHITE, 1)
|
||||
|
||||
def update(self, current_time):
|
||||
self.current_time = current_time
|
||||
for card in self.card_list:
|
||||
card.update(self.sun_value, self.current_time)
|
||||
|
||||
def createImage(self, x, y, num):
|
||||
if num == 1:
|
||||
return
|
||||
img = self.image
|
||||
rect = self.image.get_rect()
|
||||
width = rect.w
|
||||
height = rect.h
|
||||
self.image = pg.Surface((width * num, height)).convert()
|
||||
self.rect = self.image.get_rect()
|
||||
self.rect.x = x
|
||||
self.rect.y = y
|
||||
for i in range(num):
|
||||
x = i * width
|
||||
self.image.blit(img, (x,0))
|
||||
self.image.set_colorkey(c.BLACK)
|
||||
|
||||
def setupCards(self, card_list):
|
||||
self.card_list = []
|
||||
x = self.card_offset_x
|
||||
y = 8
|
||||
for index in card_list:
|
||||
x += 55
|
||||
self.card_list.append(Card(x, y, index))
|
||||
|
||||
def checkCardClick(self, mouse_pos):
|
||||
result = None
|
||||
for card in self.card_list:
|
||||
if card.checkMouseClick(mouse_pos):
|
||||
if card.canClick(self.sun_value, self.current_time):
|
||||
result = (plant_name_list[card.name_index], card)
|
||||
break
|
||||
return result
|
||||
|
||||
def checkMenuBarClick(self, mouse_pos):
|
||||
x, y = mouse_pos
|
||||
if(x >= self.rect.x and x <= self.rect.right and
|
||||
y >= self.rect.y and y <= self.rect.bottom):
|
||||
return True
|
||||
return False
|
||||
|
||||
def decreaseSunValue(self, value):
|
||||
self.sun_value -= value
|
||||
|
||||
def increaseSunValue(self, value):
|
||||
self.sun_value += value
|
||||
|
||||
def setCardFrozenTime(self, plant_name):
|
||||
for card in self.card_list:
|
||||
if plant_name_list[card.name_index] == plant_name:
|
||||
card.setFrozenTime(self.current_time)
|
||||
break
|
||||
|
||||
def drawSunValue(self):
|
||||
self.value_image = getSunValueImage(self.sun_value)
|
||||
self.value_rect = self.value_image.get_rect()
|
||||
self.value_rect.x = 21
|
||||
self.value_rect.y = self.rect.bottom - 21
|
||||
|
||||
self.image.blit(self.value_image, self.value_rect)
|
||||
|
||||
def draw(self, surface):
|
||||
self.drawSunValue()
|
||||
surface.blit(self.image, self.rect)
|
||||
for card in self.card_list:
|
||||
card.draw(surface)
|
||||
|
||||
class Panel():
|
||||
def __init__(self, card_list, sun_value):
|
||||
self.loadImages(sun_value)
|
||||
self.selected_cards = []
|
||||
self.selected_num = 0
|
||||
self.setupCards(card_list)
|
||||
|
||||
def loadFrame(self, name):
|
||||
frame = tool.GFX[name]
|
||||
rect = frame.get_rect()
|
||||
frame_rect = (rect.x, rect.y, rect.w, rect.h)
|
||||
|
||||
return tool.get_image(tool.GFX[name], *frame_rect, c.WHITE, 1)
|
||||
|
||||
def loadImages(self, sun_value):
|
||||
self.menu_image = self.loadFrame(c.MENUBAR_BACKGROUND)
|
||||
self.menu_rect = self.menu_image.get_rect()
|
||||
self.menu_rect.x = 0
|
||||
self.menu_rect.y = 0
|
||||
|
||||
self.panel_image = self.loadFrame(c.PANEL_BACKGROUND)
|
||||
self.panel_rect = self.panel_image.get_rect()
|
||||
self.panel_rect.x = 0
|
||||
self.panel_rect.y = PANEL_Y_START
|
||||
|
||||
|
||||
self.value_image = getSunValueImage(sun_value)
|
||||
self.value_rect = self.value_image.get_rect()
|
||||
self.value_rect.x = 21
|
||||
self.value_rect.y = self.menu_rect.bottom - 21
|
||||
|
||||
self.button_image = self.loadFrame(c.START_BUTTON)
|
||||
self.button_rect = self.button_image.get_rect()
|
||||
self.button_rect.x = 155
|
||||
self.button_rect.y = 547
|
||||
|
||||
def setupCards(self, card_list):
|
||||
self.card_list = []
|
||||
x = PANEL_X_START - PANEL_X_INTERNAL
|
||||
y = PANEL_Y_START + 43 - PANEL_Y_INTERNAL
|
||||
for i, index in enumerate(card_list):
|
||||
if i % 8 == 0:
|
||||
x = PANEL_X_START - PANEL_X_INTERNAL
|
||||
y += PANEL_Y_INTERNAL
|
||||
x += PANEL_X_INTERNAL
|
||||
self.card_list.append(Card(x, y, index, 0.75))
|
||||
|
||||
def checkCardClick(self, mouse_pos):
|
||||
delete_card = None
|
||||
for card in self.selected_cards:
|
||||
if delete_card: # when delete a card, move right cards to left
|
||||
card.rect.x -= 55
|
||||
elif card.checkMouseClick(mouse_pos):
|
||||
self.deleteCard(card.name_index)
|
||||
delete_card = card
|
||||
|
||||
if delete_card:
|
||||
self.selected_cards.remove(delete_card)
|
||||
self.selected_num -= 1
|
||||
|
||||
if self.selected_num == CARD_LIST_NUM:
|
||||
return
|
||||
|
||||
for card in self.card_list:
|
||||
if card.checkMouseClick(mouse_pos):
|
||||
if card.canSelect():
|
||||
self.addCard(card)
|
||||
break
|
||||
|
||||
def addCard(self, card):
|
||||
card.setSelect(False)
|
||||
y = 8
|
||||
x = 78 + self.selected_num * 55
|
||||
self.selected_cards.append(Card(x, y, card.name_index))
|
||||
self.selected_num += 1
|
||||
|
||||
def deleteCard(self, index):
|
||||
self.card_list[index].setSelect(True)
|
||||
|
||||
def checkStartButtonClick(self, mouse_pos):
|
||||
if self.selected_num < CARD_LIST_NUM:
|
||||
return False
|
||||
|
||||
x, y = mouse_pos
|
||||
if (x >= self.button_rect.x and x <= self.button_rect.right and
|
||||
y >= self.button_rect.y and y <= self.button_rect.bottom):
|
||||
return True
|
||||
return False
|
||||
|
||||
def getSelectedCards(self):
|
||||
card_index_list = []
|
||||
for card in self.selected_cards:
|
||||
card_index_list.append(card.name_index)
|
||||
return card_index_list
|
||||
|
||||
def draw(self, surface):
|
||||
self.menu_image.blit(self.value_image, self.value_rect)
|
||||
surface.blit(self.menu_image, self.menu_rect)
|
||||
surface.blit(self.panel_image, self.panel_rect)
|
||||
for card in self.card_list:
|
||||
card.draw(surface)
|
||||
for card in self.selected_cards:
|
||||
card.draw(surface)
|
||||
|
||||
if self.selected_num == CARD_LIST_NUM:
|
||||
surface.blit(self.button_image, self.button_rect)
|
||||
|
||||
class MoveCard():
|
||||
def __init__(self, x, y, card_name, plant_name, scale=0.78):
|
||||
self.loadFrame(card_name, scale)
|
||||
self.rect = self.orig_image.get_rect()
|
||||
self.rect.x = x
|
||||
self.rect.y = y
|
||||
self.rect.w = 1
|
||||
self.image = self.createShowImage()
|
||||
|
||||
self.card_name = card_name
|
||||
self.plant_name = plant_name
|
||||
self.move_timer = 0
|
||||
self.select = True
|
||||
|
||||
def loadFrame(self, name, scale):
|
||||
frame = tool.GFX[name]
|
||||
rect = frame.get_rect()
|
||||
width, height = rect.w, rect.h
|
||||
|
||||
self.orig_image = tool.get_image(frame, 0, 0, width, height, c.BLACK, scale)
|
||||
self.orig_rect = self.orig_image.get_rect()
|
||||
self.image = self.orig_image
|
||||
|
||||
def checkMouseClick(self, mouse_pos):
|
||||
x, y = mouse_pos
|
||||
if(x >= self.rect.x and x <= self.rect.right and
|
||||
y >= self.rect.y and y <= self.rect.bottom):
|
||||
return True
|
||||
return False
|
||||
|
||||
def createShowImage(self):
|
||||
'''create a part card image when card appears from left'''
|
||||
if self.rect.w < self.orig_rect.w: #create a part card image
|
||||
image = pg.Surface([self.rect.w, self.rect.h])
|
||||
image.blit(self.orig_image, (0, 0), (0, 0, self.rect.w, self.rect.h))
|
||||
self.rect.w += 1
|
||||
else:
|
||||
image = self.orig_image
|
||||
return image
|
||||
|
||||
def update(self, left_x, current_time):
|
||||
if self.move_timer == 0:
|
||||
self.move_timer = current_time
|
||||
elif (current_time - self.move_timer) >= c.CARD_MOVE_TIME:
|
||||
if self.rect.x > left_x:
|
||||
self.rect.x -= 1
|
||||
self.image = self.createShowImage()
|
||||
self.move_timer += c.CARD_MOVE_TIME
|
||||
|
||||
def draw(self, surface):
|
||||
surface.blit(self.image, self.rect)
|
||||
|
||||
class MoveBar():
|
||||
def __init__(self, card_pool):
|
||||
self.loadFrame(c.MOVEBAR_BACKGROUND)
|
||||
self.rect = self.image.get_rect()
|
||||
self.rect.x = 90
|
||||
self.rect.y = 0
|
||||
|
||||
self.card_start_x = self.rect.x + 8
|
||||
self.card_end_x = self.rect.right - 5
|
||||
self.card_pool = card_pool
|
||||
self.card_list = []
|
||||
self.create_timer = -c.MOVEBAR_CARD_FRESH_TIME
|
||||
|
||||
def loadFrame(self, name):
|
||||
frame = tool.GFX[name]
|
||||
rect = frame.get_rect()
|
||||
frame_rect = (rect.x, rect.y, rect.w, rect.h)
|
||||
|
||||
self.image = tool.get_image(tool.GFX[name], *frame_rect, c.WHITE, 1)
|
||||
|
||||
def createCard(self):
|
||||
if len(self.card_list) > 0 and self.card_list[-1].rect.right > self.card_end_x:
|
||||
return False
|
||||
x = self.card_end_x
|
||||
y = 6
|
||||
index = random.randint(0, len(self.card_pool) - 1)
|
||||
card_index = self.card_pool[index]
|
||||
card_name = card_name_list[card_index] + '_move'
|
||||
plant_name = plant_name_list[card_index]
|
||||
self.card_list.append(MoveCard(x, y, card_name, plant_name))
|
||||
return True
|
||||
|
||||
def update(self, current_time):
|
||||
self.current_time = current_time
|
||||
left_x = self.card_start_x
|
||||
for card in self.card_list:
|
||||
card.update(left_x, self.current_time)
|
||||
left_x = card.rect.right + 1
|
||||
|
||||
if(self.current_time - self.create_timer) > c.MOVEBAR_CARD_FRESH_TIME:
|
||||
if self.createCard():
|
||||
self.create_timer = self.current_time
|
||||
|
||||
def checkCardClick(self, mouse_pos):
|
||||
result = None
|
||||
for index, card in enumerate(self.card_list):
|
||||
if card.checkMouseClick(mouse_pos):
|
||||
result = (card.plant_name, card)
|
||||
break
|
||||
return result
|
||||
|
||||
def checkMenuBarClick(self, mouse_pos):
|
||||
x, y = mouse_pos
|
||||
if(x >= self.rect.x and x <= self.rect.right and
|
||||
y >= self.rect.y and y <= self.rect.bottom):
|
||||
return True
|
||||
return False
|
||||
|
||||
def deleateCard(self, card):
|
||||
self.card_list.remove(card)
|
||||
|
||||
def draw(self, surface):
|
||||
surface.blit(self.image, self.rect)
|
||||
for card in self.card_list:
|
||||
card.draw(surface)
|
@ -1,971 +0,0 @@
|
||||
__author__ = 'marble_xu'
|
||||
|
||||
import random
|
||||
import pygame as pg
|
||||
from .. import tool
|
||||
from .. import constants as c
|
||||
|
||||
class Car(pg.sprite.Sprite):
|
||||
def __init__(self, x, y, map_y):
|
||||
pg.sprite.Sprite.__init__(self)
|
||||
|
||||
rect = tool.GFX[c.CAR].get_rect()
|
||||
width, height = rect.w, rect.h
|
||||
self.image = tool.get_image(tool.GFX[c.CAR], 0, 0, width, height)
|
||||
self.rect = self.image.get_rect()
|
||||
self.rect.x = x
|
||||
self.rect.bottom = y
|
||||
self.map_y = map_y
|
||||
self.state = c.IDLE
|
||||
self.dead = False
|
||||
|
||||
def update(self, game_info):
|
||||
self.current_time = game_info[c.CURRENT_TIME]
|
||||
if self.state == c.IDLE:
|
||||
pass
|
||||
elif self.state == c.WALK:
|
||||
self.rect.x += 4
|
||||
if self.rect.x > c.SCREEN_WIDTH:
|
||||
self.dead = True
|
||||
|
||||
def setWalk(self):
|
||||
if self.state == c.IDLE:
|
||||
self.state = c.WALK
|
||||
|
||||
def draw(self, surface):
|
||||
surface.blit(self.image, self.rect)
|
||||
|
||||
class Bullet(pg.sprite.Sprite):
|
||||
def __init__(self, x, start_y, dest_y, name, damage, ice):
|
||||
pg.sprite.Sprite.__init__(self)
|
||||
|
||||
self.name = name
|
||||
self.frames = []
|
||||
self.frame_index = 0
|
||||
self.load_images()
|
||||
self.image = self.frames[self.frame_index]
|
||||
self.rect = self.image.get_rect()
|
||||
self.rect.x = x
|
||||
self.rect.y = start_y
|
||||
self.dest_y = dest_y
|
||||
self.y_vel = 4 if (dest_y > start_y) else -4
|
||||
self.x_vel = 4
|
||||
self.damage = damage
|
||||
self.ice = ice
|
||||
self.state = c.FLY
|
||||
self.current_time = 0
|
||||
|
||||
def loadFrames(self, frames, name):
|
||||
frame_list = tool.GFX[name]
|
||||
if name in tool.PLANT_RECT:
|
||||
data = tool.PLANT_RECT[name]
|
||||
x, y, width, height = data['x'], data['y'], data['width'], data['height']
|
||||
else:
|
||||
x, y = 0, 0
|
||||
rect = frame_list[0].get_rect()
|
||||
width, height = rect.w, rect.h
|
||||
|
||||
for frame in frame_list:
|
||||
frames.append(tool.get_image(frame, x, y, width, height))
|
||||
|
||||
def load_images(self):
|
||||
self.fly_frames = []
|
||||
self.explode_frames = []
|
||||
|
||||
fly_name = self.name
|
||||
if self.name == c.BULLET_MUSHROOM:
|
||||
explode_name = 'BulletMushRoomExplode'
|
||||
else:
|
||||
explode_name = 'PeaNormalExplode'
|
||||
|
||||
self.loadFrames(self.fly_frames, fly_name)
|
||||
self.loadFrames(self.explode_frames, explode_name)
|
||||
|
||||
self.frames = self.fly_frames
|
||||
|
||||
def update(self, game_info):
|
||||
self.current_time = game_info[c.CURRENT_TIME]
|
||||
if self.state == c.FLY:
|
||||
if self.rect.y != self.dest_y:
|
||||
self.rect.y += self.y_vel
|
||||
if self.y_vel * (self.dest_y - self.rect.y) < 0:
|
||||
self.rect.y = self.dest_y
|
||||
self.rect.x += self.x_vel
|
||||
if self.rect.x > c.SCREEN_WIDTH:
|
||||
self.kill()
|
||||
elif self.state == c.EXPLODE:
|
||||
if(self.current_time - self.explode_timer) > 500:
|
||||
self.kill()
|
||||
|
||||
def setExplode(self):
|
||||
self.state = c.EXPLODE
|
||||
self.explode_timer = self.current_time
|
||||
self.frames = self.explode_frames
|
||||
self.image = self.frames[self.frame_index]
|
||||
|
||||
def draw(self, surface):
|
||||
surface.blit(self.image, self.rect)
|
||||
|
||||
class Plant(pg.sprite.Sprite):
|
||||
def __init__(self, x, y, name, health, bullet_group, scale=1):
|
||||
pg.sprite.Sprite.__init__(self)
|
||||
|
||||
self.frames = []
|
||||
self.frame_index = 0
|
||||
self.loadImages(name, scale)
|
||||
self.frame_num = len(self.frames)
|
||||
self.image = self.frames[self.frame_index]
|
||||
self.rect = self.image.get_rect()
|
||||
self.rect.centerx = x
|
||||
self.rect.bottom = y
|
||||
|
||||
self.name = name
|
||||
self.health = health
|
||||
self.state = c.IDLE
|
||||
self.bullet_group = bullet_group
|
||||
self.can_sleep = False
|
||||
self.animate_timer = 0
|
||||
self.animate_interval = 100
|
||||
self.hit_timer = 0
|
||||
|
||||
def loadFrames(self, frames, name, scale, color=c.BLACK):
|
||||
frame_list = tool.GFX[name]
|
||||
if name in tool.PLANT_RECT:
|
||||
data = tool.PLANT_RECT[name]
|
||||
x, y, width, height = data['x'], data['y'], data['width'], data['height']
|
||||
else:
|
||||
x, y = 0, 0
|
||||
rect = frame_list[0].get_rect()
|
||||
width, height = rect.w, rect.h
|
||||
|
||||
for frame in frame_list:
|
||||
frames.append(tool.get_image(frame, x, y, width, height, color, scale))
|
||||
|
||||
def loadImages(self, name, scale):
|
||||
self.loadFrames(self.frames, name, scale)
|
||||
|
||||
def changeFrames(self, frames):
|
||||
'''change image frames and modify rect position'''
|
||||
self.frames = frames
|
||||
self.frame_num = len(self.frames)
|
||||
self.frame_index = 0
|
||||
|
||||
bottom = self.rect.bottom
|
||||
x = self.rect.x
|
||||
self.image = self.frames[self.frame_index]
|
||||
self.rect = self.image.get_rect()
|
||||
self.rect.bottom = bottom
|
||||
self.rect.x = x
|
||||
|
||||
def update(self, game_info):
|
||||
self.current_time = game_info[c.CURRENT_TIME]
|
||||
self.handleState()
|
||||
self.animation()
|
||||
|
||||
def handleState(self):
|
||||
if self.state == c.IDLE:
|
||||
self.idling()
|
||||
elif self.state == c.ATTACK:
|
||||
self.attacking()
|
||||
elif self.state == c.DIGEST:
|
||||
self.digest()
|
||||
|
||||
def idling(self):
|
||||
pass
|
||||
|
||||
def attacking(self):
|
||||
pass
|
||||
|
||||
def digest(self):
|
||||
pass
|
||||
|
||||
def animation(self):
|
||||
if (self.current_time - self.animate_timer) > self.animate_interval:
|
||||
self.frame_index += 1
|
||||
if self.frame_index >= self.frame_num:
|
||||
self.frame_index = 0
|
||||
self.animate_timer = self.current_time
|
||||
|
||||
self.image = self.frames[self.frame_index]
|
||||
if(self.current_time - self.hit_timer) >= 200:
|
||||
self.image.set_alpha(255)
|
||||
else:
|
||||
self.image.set_alpha(192)
|
||||
|
||||
def canAttack(self, zombie):
|
||||
if (self.state != c.SLEEP and zombie.state != c.DIE and
|
||||
self.rect.x <= zombie.rect.right):
|
||||
return True
|
||||
return False
|
||||
|
||||
def setAttack(self):
|
||||
self.state = c.ATTACK
|
||||
|
||||
def setIdle(self):
|
||||
self.state = c.IDLE
|
||||
self.is_attacked = False
|
||||
|
||||
def setSleep(self):
|
||||
self.state = c.SLEEP
|
||||
self.changeFrames(self.sleep_frames)
|
||||
|
||||
def setDamage(self, damage, zombie):
|
||||
self.health -= damage
|
||||
self.hit_timer = self.current_time
|
||||
if self.health == 0:
|
||||
self.kill_zombie = zombie
|
||||
|
||||
def getPosition(self):
|
||||
return self.rect.centerx, self.rect.bottom
|
||||
|
||||
class Sun(Plant):
|
||||
def __init__(self, x, y, dest_x, dest_y, is_big=True):
|
||||
if is_big:
|
||||
scale = 0.9
|
||||
self.sun_value = c.SUN_VALUE
|
||||
else:
|
||||
scale = 0.6
|
||||
self.sun_value = 12
|
||||
Plant.__init__(self, x, y, c.SUN, 0, None, scale)
|
||||
self.move_speed = 1
|
||||
self.dest_x = dest_x
|
||||
self.dest_y = dest_y
|
||||
self.die_timer = 0
|
||||
|
||||
def handleState(self):
|
||||
if self.rect.centerx != self.dest_x:
|
||||
self.rect.centerx += self.move_speed if self.rect.centerx < self.dest_x else -self.move_speed
|
||||
if self.rect.bottom != self.dest_y:
|
||||
self.rect.bottom += self.move_speed if self.rect.bottom < self.dest_y else -self.move_speed
|
||||
|
||||
if self.rect.centerx == self.dest_x and self.rect.bottom == self.dest_y:
|
||||
if self.die_timer == 0:
|
||||
self.die_timer = self.current_time
|
||||
elif(self.current_time - self.die_timer) > c.SUN_LIVE_TIME:
|
||||
self.state = c.DIE
|
||||
self.kill()
|
||||
|
||||
def checkCollision(self, x, y):
|
||||
if self.state == c.DIE:
|
||||
return False
|
||||
if(x >= self.rect.x and x <= self.rect.right and
|
||||
y >= self.rect.y and y <= self.rect.bottom):
|
||||
self.state = c.DIE
|
||||
self.kill()
|
||||
return True
|
||||
return False
|
||||
|
||||
class SunFlower(Plant):
|
||||
def __init__(self, x, y, sun_group):
|
||||
Plant.__init__(self, x, y, c.SUNFLOWER, c.PLANT_HEALTH, None)
|
||||
self.sun_timer = 0
|
||||
self.sun_group = sun_group
|
||||
|
||||
def idling(self):
|
||||
if self.sun_timer == 0:
|
||||
self.sun_timer = self.current_time - (c.FLOWER_SUN_INTERVAL - 6000)
|
||||
elif (self.current_time - self.sun_timer) > c.FLOWER_SUN_INTERVAL:
|
||||
self.sun_group.add(Sun(self.rect.centerx, self.rect.bottom, self.rect.right, self.rect.bottom + self.rect.h // 2))
|
||||
self.sun_timer = self.current_time
|
||||
|
||||
class PeaShooter(Plant):
|
||||
def __init__(self, x, y, bullet_group):
|
||||
Plant.__init__(self, x, y, c.PEASHOOTER, c.PLANT_HEALTH, bullet_group)
|
||||
self.shoot_timer = 0
|
||||
|
||||
def attacking(self):
|
||||
if (self.current_time - self.shoot_timer) > 2000:
|
||||
self.bullet_group.add(Bullet(self.rect.right, self.rect.y, self.rect.y,
|
||||
c.BULLET_PEA, c.BULLET_DAMAGE_NORMAL, False))
|
||||
self.shoot_timer = self.current_time
|
||||
|
||||
class RepeaterPea(Plant):
|
||||
def __init__(self, x, y, bullet_group):
|
||||
Plant.__init__(self, x, y, c.REPEATERPEA, c.PLANT_HEALTH, bullet_group)
|
||||
self.shoot_timer = 0
|
||||
|
||||
def attacking(self):
|
||||
if (self.current_time - self.shoot_timer) > 2000:
|
||||
self.bullet_group.add(Bullet(self.rect.right, self.rect.y, self.rect.y,
|
||||
c.BULLET_PEA, c.BULLET_DAMAGE_NORMAL, False))
|
||||
self.bullet_group.add(Bullet(self.rect.right + 40, self.rect.y, self.rect.y,
|
||||
c.BULLET_PEA, c.BULLET_DAMAGE_NORMAL, False))
|
||||
self.shoot_timer = self.current_time
|
||||
|
||||
class ThreePeaShooter(Plant):
|
||||
def __init__(self, x, y, bullet_groups, map_y):
|
||||
Plant.__init__(self, x, y, c.THREEPEASHOOTER, c.PLANT_HEALTH, None)
|
||||
self.shoot_timer = 0
|
||||
self.map_y = map_y
|
||||
self.bullet_groups = bullet_groups
|
||||
|
||||
def attacking(self):
|
||||
if (self.current_time - self.shoot_timer) > 2000:
|
||||
offset_y = 9 # modify bullet in the same y position with bullets of other plants
|
||||
for i in range(3):
|
||||
tmp_y = self.map_y + (i - 1)
|
||||
if tmp_y < 0 or tmp_y >= c.GRID_Y_LEN:
|
||||
continue
|
||||
dest_y = self.rect.y + (i - 1) * c.GRID_Y_SIZE + offset_y
|
||||
self.bullet_groups[tmp_y].add(Bullet(self.rect.right, self.rect.y, dest_y,
|
||||
c.BULLET_PEA, c.BULLET_DAMAGE_NORMAL, False))
|
||||
self.shoot_timer = self.current_time
|
||||
|
||||
class SnowPeaShooter(Plant):
|
||||
def __init__(self, x, y, bullet_group):
|
||||
Plant.__init__(self, x, y, c.SNOWPEASHOOTER, c.PLANT_HEALTH, bullet_group)
|
||||
self.shoot_timer = 0
|
||||
|
||||
def attacking(self):
|
||||
if (self.current_time - self.shoot_timer) > 2000:
|
||||
self.bullet_group.add(Bullet(self.rect.right, self.rect.y, self.rect.y,
|
||||
c.BULLET_PEA_ICE, c.BULLET_DAMAGE_NORMAL, True))
|
||||
self.shoot_timer = self.current_time
|
||||
|
||||
class WallNut(Plant):
|
||||
def __init__(self, x, y):
|
||||
Plant.__init__(self, x, y, c.WALLNUT, c.WALLNUT_HEALTH, None)
|
||||
self.load_images()
|
||||
self.cracked1 = False
|
||||
self.cracked2 = False
|
||||
|
||||
def load_images(self):
|
||||
self.cracked1_frames = []
|
||||
self.cracked2_frames = []
|
||||
|
||||
cracked1_frames_name = self.name + '_cracked1'
|
||||
cracked2_frames_name = self.name + '_cracked2'
|
||||
|
||||
self.loadFrames(self.cracked1_frames, cracked1_frames_name, 1)
|
||||
self.loadFrames(self.cracked2_frames, cracked2_frames_name, 1)
|
||||
|
||||
def idling(self):
|
||||
if not self.cracked1 and self.health <= c.WALLNUT_CRACKED1_HEALTH:
|
||||
self.changeFrames(self.cracked1_frames)
|
||||
self.cracked1 = True
|
||||
elif not self.cracked2 and self.health <= c.WALLNUT_CRACKED2_HEALTH:
|
||||
self.changeFrames(self.cracked2_frames)
|
||||
self.cracked2 = True
|
||||
|
||||
class CherryBomb(Plant):
|
||||
def __init__(self, x, y):
|
||||
Plant.__init__(self, x, y, c.CHERRYBOMB, c.WALLNUT_HEALTH, None)
|
||||
self.state = c.ATTACK
|
||||
self.start_boom = False
|
||||
self.bomb_timer = 0
|
||||
self.explode_y_range = 1
|
||||
self.explode_x_range = c.GRID_X_SIZE
|
||||
|
||||
def setBoom(self):
|
||||
frame = tool.GFX[c.CHERRY_BOOM_IMAGE]
|
||||
rect = frame.get_rect()
|
||||
width, height = rect.w, rect.h
|
||||
|
||||
old_rect = self.rect
|
||||
image = tool.get_image(frame, 0, 0, width, height, c.BLACK, 1)
|
||||
self.image = image
|
||||
self.rect = image.get_rect()
|
||||
self.rect.centerx = old_rect.centerx
|
||||
self.rect.centery = old_rect.centery
|
||||
self.start_boom = True
|
||||
|
||||
def animation(self):
|
||||
if self.start_boom:
|
||||
if self.bomb_timer == 0:
|
||||
self.bomb_timer = self.current_time
|
||||
elif(self.current_time - self.bomb_timer) > 500:
|
||||
self.health = 0
|
||||
else:
|
||||
if (self.current_time - self.animate_timer) > 100:
|
||||
self.frame_index += 1
|
||||
if self.frame_index >= self.frame_num:
|
||||
self.setBoom()
|
||||
return
|
||||
self.animate_timer = self.current_time
|
||||
|
||||
self.image = self.frames[self.frame_index]
|
||||
|
||||
class Chomper(Plant):
|
||||
def __init__(self, x, y):
|
||||
Plant.__init__(self, x, y, c.CHOMPER, c.PLANT_HEALTH, None)
|
||||
self.animate_interval = 250
|
||||
self.digest_timer = 0
|
||||
self.digest_interval = 15000
|
||||
self.attack_zombie = None
|
||||
self.zombie_group = None
|
||||
|
||||
def loadImages(self, name, scale):
|
||||
self.idle_frames = []
|
||||
self.attack_frames = []
|
||||
self.digest_frames = []
|
||||
|
||||
idle_name = name
|
||||
attack_name = name + 'Attack'
|
||||
digest_name = name + 'Digest'
|
||||
|
||||
frame_list = [self.idle_frames, self.attack_frames, self.digest_frames]
|
||||
name_list = [idle_name, attack_name, digest_name]
|
||||
scale_list = [1, 1, 1]
|
||||
rect_list = [(0, 0, 100, 114), None, None]
|
||||
|
||||
for i, name in enumerate(name_list):
|
||||
self.loadFrames(frame_list[i], name, scale_list[i])
|
||||
|
||||
self.frames = self.idle_frames
|
||||
|
||||
def canAttack(self, zombie):
|
||||
if (self.state == c.IDLE and zombie.state != c.DIGEST and
|
||||
self.rect.x <= zombie.rect.right and
|
||||
(self.rect.right + c.GRID_X_SIZE//3 >= zombie.rect.x)):
|
||||
return True
|
||||
return False
|
||||
|
||||
def setIdle(self):
|
||||
self.state = c.IDLE
|
||||
self.changeFrames(self.idle_frames)
|
||||
|
||||
def setAttack(self, zombie, zombie_group):
|
||||
self.attack_zombie = zombie
|
||||
self.zombie_group = zombie_group
|
||||
self.state = c.ATTACK
|
||||
self.changeFrames(self.attack_frames)
|
||||
|
||||
def setDigest(self):
|
||||
self.state = c.DIGEST
|
||||
self.changeFrames(self.digest_frames)
|
||||
|
||||
def attacking(self):
|
||||
if self.frame_index == (self.frame_num - 3):
|
||||
self.zombie_group.remove(self.attack_zombie)
|
||||
if (self.frame_index + 1) == self.frame_num:
|
||||
self.setDigest()
|
||||
|
||||
def digest(self):
|
||||
if self.digest_timer == 0:
|
||||
self.digest_timer = self.current_time
|
||||
elif (self.current_time - self.digest_timer) > self.digest_interval:
|
||||
self.digest_timer = 0
|
||||
self.attack_zombie.kill()
|
||||
self.setIdle()
|
||||
|
||||
class PuffShroom(Plant):
|
||||
def __init__(self, x, y, bullet_group):
|
||||
Plant.__init__(self, x, y, c.PUFFSHROOM, c.PLANT_HEALTH, bullet_group)
|
||||
self.can_sleep = True
|
||||
self.shoot_timer = 0
|
||||
|
||||
def loadImages(self, name, scale):
|
||||
self.idle_frames = []
|
||||
self.sleep_frames = []
|
||||
|
||||
idle_name = name
|
||||
sleep_name = name + 'Sleep'
|
||||
|
||||
frame_list = [self.idle_frames, self.sleep_frames]
|
||||
name_list = [idle_name, sleep_name]
|
||||
|
||||
for i, name in enumerate(name_list):
|
||||
self.loadFrames(frame_list[i], name, 1)
|
||||
|
||||
self.frames = self.idle_frames
|
||||
|
||||
def attacking(self):
|
||||
if (self.current_time - self.shoot_timer) > 3000:
|
||||
self.bullet_group.add(Bullet(self.rect.right, self.rect.y + 10, self.rect.y + 10,
|
||||
c.BULLET_MUSHROOM, c.BULLET_DAMAGE_NORMAL, True))
|
||||
self.shoot_timer = self.current_time
|
||||
|
||||
def canAttack(self, zombie):
|
||||
if (self.rect.x <= zombie.rect.right and
|
||||
(self.rect.right + c.GRID_X_SIZE * 4 >= zombie.rect.x)):
|
||||
return True
|
||||
return False
|
||||
|
||||
class PotatoMine(Plant):
|
||||
def __init__(self, x, y):
|
||||
Plant.__init__(self, x, y, c.POTATOMINE, c.PLANT_HEALTH, None)
|
||||
self.animate_interval = 300
|
||||
self.is_init = True
|
||||
self.init_timer = 0
|
||||
self.bomb_timer = 0
|
||||
self.explode_y_range = 0
|
||||
self.explode_x_range = c.GRID_X_SIZE//3 * 2
|
||||
|
||||
def loadImages(self, name, scale):
|
||||
self.init_frames = []
|
||||
self.idle_frames = []
|
||||
self.explode_frames = []
|
||||
|
||||
init_name = name + 'Init'
|
||||
idle_name = name
|
||||
explode_name = name + 'Explode'
|
||||
|
||||
frame_list = [self.init_frames, self.idle_frames, self.explode_frames]
|
||||
name_list = [init_name, idle_name, explode_name]
|
||||
|
||||
for i, name in enumerate(name_list):
|
||||
self.loadFrames(frame_list[i], name, 1, c.WHITE)
|
||||
|
||||
self.frames = self.init_frames
|
||||
|
||||
def idling(self):
|
||||
if self.is_init:
|
||||
if self.init_timer == 0:
|
||||
self.init_timer = self.current_time
|
||||
elif (self.current_time - self.init_timer) > 15000:
|
||||
self.changeFrames(self.idle_frames)
|
||||
self.is_init = False
|
||||
|
||||
def canAttack(self, zombie):
|
||||
if (not self.is_init and zombie.rect.right >= self.rect.x and
|
||||
(zombie.rect.x - self.rect.x) <= self.explode_x_range):
|
||||
return True
|
||||
return False
|
||||
|
||||
def attacking(self):
|
||||
if self.bomb_timer == 0:
|
||||
self.bomb_timer = self.current_time
|
||||
self.changeFrames(self.explode_frames)
|
||||
elif (self.current_time - self.bomb_timer) > 500:
|
||||
self.health = 0
|
||||
|
||||
class Squash(Plant):
|
||||
def __init__(self, x, y):
|
||||
Plant.__init__(self, x, y, c.SQUASH, c.PLANT_HEALTH, None)
|
||||
self.orig_pos = (x, y)
|
||||
self.aim_timer = 0
|
||||
self.squashing = False
|
||||
|
||||
def loadImages(self, name, scale):
|
||||
self.idle_frames = []
|
||||
self.aim_frames = []
|
||||
self.attack_frames = []
|
||||
|
||||
idle_name = name
|
||||
aim_name = name + 'Aim'
|
||||
attack_name = name + 'Attack'
|
||||
|
||||
frame_list = [self.idle_frames, self.aim_frames, self.attack_frames]
|
||||
name_list = [idle_name, aim_name, attack_name]
|
||||
|
||||
for i, name in enumerate(name_list):
|
||||
self.loadFrames(frame_list[i], name, 1, c.WHITE)
|
||||
|
||||
self.frames = self.idle_frames
|
||||
|
||||
def canAttack(self, zombie):
|
||||
if (self.state == c.IDLE and self.rect.x <= zombie.rect.right and
|
||||
(self.rect.right + c.GRID_X_SIZE >= zombie.rect.x)):
|
||||
return True
|
||||
return False
|
||||
|
||||
def setAttack(self, zombie, zombie_group):
|
||||
self.attack_zombie = zombie
|
||||
self.zombie_group = zombie_group
|
||||
self.state = c.ATTACK
|
||||
|
||||
def attacking(self):
|
||||
if self.squashing:
|
||||
if self.frame_index == 2:
|
||||
self.zombie_group.remove(self.attack_zombie)
|
||||
if (self.frame_index + 1) == self.frame_num:
|
||||
self.attack_zombie.kill()
|
||||
self.health = 0
|
||||
elif self.aim_timer == 0:
|
||||
self.aim_timer = self.current_time
|
||||
self.changeFrames(self.aim_frames)
|
||||
elif (self.current_time - self.aim_timer) > 1000:
|
||||
self.changeFrames(self.attack_frames)
|
||||
self.rect.centerx = self.attack_zombie.rect.centerx
|
||||
self.squashing = True
|
||||
self.animate_interval = 300
|
||||
|
||||
def getPosition(self):
|
||||
return self.orig_pos
|
||||
|
||||
class Spikeweed(Plant):
|
||||
def __init__(self, x, y):
|
||||
Plant.__init__(self, x, y, c.SPIKEWEED, c.PLANT_HEALTH, None)
|
||||
self.animate_interval = 200
|
||||
self.attack_timer = 0
|
||||
|
||||
def loadImages(self, name, scale):
|
||||
self.loadFrames(self.frames, name, 0.9, c.WHITE)
|
||||
|
||||
def setIdle(self):
|
||||
print('spikeweed idle')
|
||||
self.animate_interval = 200
|
||||
self.state = c.IDLE
|
||||
|
||||
def canAttack(self, zombie):
|
||||
if (self.rect.x <= zombie.rect.right and
|
||||
(self.rect.right >= zombie.rect.x)):
|
||||
return True
|
||||
return False
|
||||
|
||||
def setAttack(self, zombie_group):
|
||||
self.zombie_group = zombie_group
|
||||
self.animate_interval = 50
|
||||
self.state = c.ATTACK
|
||||
|
||||
def attacking(self):
|
||||
if (self.current_time - self.attack_timer) > 2000:
|
||||
self.attack_timer = self.current_time
|
||||
for zombie in self.zombie_group:
|
||||
if self.canAttack(zombie):
|
||||
zombie.setDamage(1, False)
|
||||
|
||||
class Jalapeno(Plant):
|
||||
def __init__(self, x, y):
|
||||
Plant.__init__(self, x, y, c.JALAPENO, c.PLANT_HEALTH, None)
|
||||
self.orig_pos = (x, y)
|
||||
self.state = c.ATTACK
|
||||
self.start_explode = False
|
||||
self.explode_y_range = 0
|
||||
self.explode_x_range = 377
|
||||
|
||||
def loadImages(self, name, scale):
|
||||
self.explode_frames = []
|
||||
explode_name = name + 'Explode'
|
||||
self.loadFrames(self.explode_frames, explode_name, 1, c.WHITE)
|
||||
|
||||
self.loadFrames(self.frames, name, 1, c.WHITE)
|
||||
|
||||
def setExplode(self):
|
||||
self.changeFrames(self.explode_frames)
|
||||
self.animate_timer = self.current_time
|
||||
self.rect.x = c.MAP_OFFSET_X
|
||||
self.start_explode = True
|
||||
|
||||
def animation(self):
|
||||
if self.start_explode:
|
||||
if(self.current_time - self.animate_timer) > 100:
|
||||
self.frame_index += 1
|
||||
if self.frame_index >= self.frame_num:
|
||||
self.health = 0
|
||||
return
|
||||
self.animate_timer = self.current_time
|
||||
else:
|
||||
if (self.current_time - self.animate_timer) > 100:
|
||||
self.frame_index += 1
|
||||
if self.frame_index >= self.frame_num:
|
||||
self.setExplode()
|
||||
return
|
||||
self.animate_timer = self.current_time
|
||||
self.image = self.frames[self.frame_index]
|
||||
|
||||
def getPosition(self):
|
||||
return self.orig_pos
|
||||
|
||||
class ScaredyShroom(Plant):
|
||||
def __init__(self, x, y, bullet_group):
|
||||
Plant.__init__(self, x, y, c.SCAREDYSHROOM, c.PLANT_HEALTH, bullet_group)
|
||||
self.can_sleep = True
|
||||
self.shoot_timer = 0
|
||||
self.cry_x_range = c.GRID_X_SIZE * 2
|
||||
|
||||
def loadImages(self, name, scale):
|
||||
self.idle_frames = []
|
||||
self.cry_frames = []
|
||||
self.sleep_frames = []
|
||||
|
||||
idle_name = name
|
||||
cry_name = name + 'Cry'
|
||||
sleep_name = name + 'Sleep'
|
||||
|
||||
frame_list = [self.idle_frames, self.cry_frames, self.sleep_frames]
|
||||
name_list = [idle_name, cry_name, sleep_name]
|
||||
|
||||
for i, name in enumerate(name_list):
|
||||
self.loadFrames(frame_list[i], name, 1, c.WHITE)
|
||||
|
||||
self.frames = self.idle_frames
|
||||
|
||||
def needCry(self, zombie):
|
||||
if (zombie.state != c.DIE and self.rect.x <= zombie.rect.right and
|
||||
self.rect.x + self.cry_x_range > zombie.rect.x):
|
||||
return True
|
||||
return False
|
||||
|
||||
def setCry(self):
|
||||
self.state = c.CRY
|
||||
self.changeFrames(self.cry_frames)
|
||||
|
||||
def setAttack(self):
|
||||
self.state = c.ATTACK
|
||||
self.changeFrames(self.idle_frames)
|
||||
|
||||
def setIdle(self):
|
||||
self.state = c.IDLE
|
||||
self.changeFrames(self.idle_frames)
|
||||
|
||||
def attacking(self):
|
||||
if (self.current_time - self.shoot_timer) > 2000:
|
||||
self.bullet_group.add(Bullet(self.rect.right, self.rect.y + 40, self.rect.y + 40,
|
||||
c.BULLET_MUSHROOM, c.BULLET_DAMAGE_NORMAL, True))
|
||||
self.shoot_timer = self.current_time
|
||||
|
||||
class SunShroom(Plant):
|
||||
def __init__(self, x, y, sun_group):
|
||||
Plant.__init__(self, x, y, c.SUNSHROOM, c.PLANT_HEALTH, None)
|
||||
self.can_sleep = True
|
||||
self.animate_interval = 200
|
||||
self.sun_timer = 0
|
||||
self.sun_group = sun_group
|
||||
self.is_big = False
|
||||
self.change_timer = 0
|
||||
|
||||
def loadImages(self, name, scale):
|
||||
self.idle_frames = []
|
||||
self.big_frames = []
|
||||
self.sleep_frames = []
|
||||
|
||||
idle_name = name
|
||||
big_name = name + 'Big'
|
||||
sleep_name = name + 'Sleep'
|
||||
|
||||
frame_list = [self.idle_frames, self.big_frames, self.sleep_frames]
|
||||
name_list = [idle_name, big_name, sleep_name]
|
||||
|
||||
for i, name in enumerate(name_list):
|
||||
self.loadFrames(frame_list[i], name, 1, c.WHITE)
|
||||
|
||||
self.frames = self.idle_frames
|
||||
|
||||
def idling(self):
|
||||
if not self.is_big:
|
||||
if self.change_timer == 0:
|
||||
self.change_timer = self.current_time
|
||||
elif (self.current_time - self.change_timer) > 25000:
|
||||
self.changeFrames(self.big_frames)
|
||||
self.is_big = True
|
||||
|
||||
if self.sun_timer == 0:
|
||||
self.sun_timer = self.current_time - (c.FLOWER_SUN_INTERVAL - 6000)
|
||||
elif (self.current_time - self.sun_timer) > c.FLOWER_SUN_INTERVAL:
|
||||
self.sun_group.add(Sun(self.rect.centerx, self.rect.bottom, self.rect.right,
|
||||
self.rect.bottom + self.rect.h // 2, self.is_big))
|
||||
self.sun_timer = self.current_time
|
||||
|
||||
class IceShroom(Plant):
|
||||
def __init__(self, x, y):
|
||||
Plant.__init__(self, x, y, c.ICESHROOM, c.PLANT_HEALTH, None)
|
||||
self.can_sleep = True
|
||||
self.orig_pos = (x, y)
|
||||
self.start_freeze = False
|
||||
|
||||
def loadImages(self, name, scale):
|
||||
self.idle_frames = []
|
||||
self.snow_frames = []
|
||||
self.sleep_frames = []
|
||||
self.trap_frames = []
|
||||
|
||||
idle_name = name
|
||||
snow_name = name + 'Snow'
|
||||
sleep_name = name + 'Sleep'
|
||||
trap_name = name + 'Trap'
|
||||
|
||||
frame_list = [self.idle_frames, self.snow_frames, self.sleep_frames, self.trap_frames]
|
||||
name_list = [idle_name, snow_name, sleep_name, trap_name]
|
||||
scale_list = [1, 1.5, 1, 1]
|
||||
|
||||
for i, name in enumerate(name_list):
|
||||
self.loadFrames(frame_list[i], name, scale_list[i], c.WHITE)
|
||||
|
||||
self.frames = self.idle_frames
|
||||
|
||||
def setFreeze(self):
|
||||
self.changeFrames(self.snow_frames)
|
||||
self.animate_timer = self.current_time
|
||||
self.rect.x = c.MAP_OFFSET_X
|
||||
self.rect.y = c.MAP_OFFSET_Y
|
||||
self.start_freeze = True
|
||||
|
||||
def animation(self):
|
||||
if self.start_freeze:
|
||||
if(self.current_time - self.animate_timer) > 500:
|
||||
self.frame_index += 1
|
||||
if self.frame_index >= self.frame_num:
|
||||
self.health = 0
|
||||
return
|
||||
self.animate_timer = self.current_time
|
||||
else:
|
||||
if (self.current_time - self.animate_timer) > 100:
|
||||
self.frame_index += 1
|
||||
if self.frame_index >= self.frame_num:
|
||||
if self.state == c.SLEEP:
|
||||
self.frame_index = 0
|
||||
else:
|
||||
self.setFreeze()
|
||||
return
|
||||
self.animate_timer = self.current_time
|
||||
self.image = self.frames[self.frame_index]
|
||||
|
||||
def getPosition(self):
|
||||
return self.orig_pos
|
||||
|
||||
class HypnoShroom(Plant):
|
||||
def __init__(self, x, y):
|
||||
Plant.__init__(self, x, y, c.HYPNOSHROOM, 1, None)
|
||||
self.can_sleep = True
|
||||
self.animate_interval = 200
|
||||
|
||||
def loadImages(self, name, scale):
|
||||
self.idle_frames = []
|
||||
self.sleep_frames = []
|
||||
|
||||
idle_name = name
|
||||
sleep_name = name + 'Sleep'
|
||||
|
||||
frame_list = [self.idle_frames, self.sleep_frames]
|
||||
name_list = [idle_name, sleep_name]
|
||||
|
||||
for i, name in enumerate(name_list):
|
||||
self.loadFrames(frame_list[i], name, 1, c.WHITE)
|
||||
|
||||
self.frames = self.idle_frames
|
||||
|
||||
class WallNutBowling(Plant):
|
||||
def __init__(self, x, y, map_y, level):
|
||||
Plant.__init__(self, x, y, c.WALLNUTBOWLING, 1, None)
|
||||
self.map_y = map_y
|
||||
self.level = level
|
||||
self.init_rect = self.rect.copy()
|
||||
self.rotate_degree = 0
|
||||
self.animate_interval = 200
|
||||
self.move_timer = 0
|
||||
self.move_interval = 70
|
||||
self.vel_x = random.randint(12, 15)
|
||||
self.vel_y = 0
|
||||
self.disable_hit_y = -1
|
||||
|
||||
def loadImages(self, name, scale):
|
||||
self.loadFrames(self.frames, name, 1, c.WHITE)
|
||||
|
||||
def idling(self):
|
||||
if self.move_timer == 0:
|
||||
self.move_timer = self.current_time
|
||||
elif (self.current_time - self.move_timer) >= self.move_interval:
|
||||
self.rotate_degree = (self.rotate_degree - 30) % 360
|
||||
self.init_rect.x += self.vel_x
|
||||
self.init_rect.y += self.vel_y
|
||||
self.handleMapYPosition()
|
||||
if self.shouldChangeDirection():
|
||||
self.changeDirection(-1)
|
||||
if self.init_rect.x > c.SCREEN_WIDTH:
|
||||
self.health = 0
|
||||
self.move_timer += self.move_interval
|
||||
|
||||
def canHit(self, map_y):
|
||||
if self.disable_hit_y == map_y:
|
||||
return False
|
||||
return True
|
||||
|
||||
def handleMapYPosition(self):
|
||||
_, map_y1 = self.level.map.getMapIndex(self.init_rect.x, self.init_rect.centery)
|
||||
_, map_y2 = self.level.map.getMapIndex(self.init_rect.x, self.init_rect.bottom)
|
||||
if self.map_y != map_y1 and map_y1 == map_y2:
|
||||
# wallnut bowls to another row, should modify which plant group it belongs to
|
||||
self.level.plant_groups[self.map_y].remove(self)
|
||||
self.level.plant_groups[map_y1].add(self)
|
||||
self.map_y = map_y1
|
||||
|
||||
def shouldChangeDirection(self):
|
||||
if self.init_rect.centery <= c.MAP_OFFSET_Y:
|
||||
return True
|
||||
elif self.init_rect.bottom + 20 >= c.SCREEN_HEIGHT:
|
||||
return True
|
||||
return False
|
||||
|
||||
def changeDirection(self, map_y):
|
||||
if self.vel_y == 0:
|
||||
if self.map_y == 0:
|
||||
direc = 1
|
||||
elif self.map_y == (c.GRID_Y_LEN-1):
|
||||
direc = -1
|
||||
else:
|
||||
if random.randint(0, 1) == 0:
|
||||
direc = 1
|
||||
else:
|
||||
direc = -1
|
||||
self.vel_y = self.vel_x * direc
|
||||
else:
|
||||
self.vel_y = - self.vel_y
|
||||
|
||||
self.disable_hit_y = map_y
|
||||
|
||||
def animation(self):
|
||||
if (self.current_time - self.animate_timer) > self.animate_interval:
|
||||
self.frame_index += 1
|
||||
if self.frame_index >= self.frame_num:
|
||||
self.frame_index = 0
|
||||
self.animate_timer = self.current_time
|
||||
|
||||
image = self.frames[self.frame_index]
|
||||
self.image = pg.transform.rotate(image, self.rotate_degree)
|
||||
# must keep the center postion of image when rotate
|
||||
self.rect = self.image.get_rect(center=self.init_rect.center)
|
||||
|
||||
class RedWallNutBowling(Plant):
|
||||
def __init__(self, x, y):
|
||||
Plant.__init__(self, x, y, c.REDWALLNUTBOWLING, 1, None)
|
||||
self.orig_y = y
|
||||
self.explode_timer = 0
|
||||
self.explode_y_range = 1
|
||||
self.explode_x_range = c.GRID_X_SIZE
|
||||
self.init_rect = self.rect.copy()
|
||||
self.rotate_degree = 0
|
||||
self.animate_interval = 200
|
||||
self.move_timer = 0
|
||||
self.move_interval = 70
|
||||
self.vel_x = random.randint(12, 15)
|
||||
|
||||
def loadImages(self, name, scale):
|
||||
self.idle_frames = []
|
||||
self.explode_frames = []
|
||||
|
||||
idle_name = name
|
||||
explode_name = name + 'Explode'
|
||||
|
||||
frame_list = [self.idle_frames, self.explode_frames]
|
||||
name_list = [idle_name, explode_name]
|
||||
|
||||
for i, name in enumerate(name_list):
|
||||
self.loadFrames(frame_list[i], name, 1, c.WHITE)
|
||||
|
||||
self.frames = self.idle_frames
|
||||
|
||||
def idling(self):
|
||||
if self.move_timer == 0:
|
||||
self.move_timer = self.current_time
|
||||
elif (self.current_time - self.move_timer) >= self.move_interval:
|
||||
self.rotate_degree = (self.rotate_degree - 30) % 360
|
||||
self.init_rect.x += self.vel_x
|
||||
if self.init_rect.x > c.SCREEN_WIDTH:
|
||||
self.health = 0
|
||||
self.move_timer += self.move_interval
|
||||
|
||||
def attacking(self):
|
||||
if self.explode_timer == 0:
|
||||
self.explode_timer = self.current_time
|
||||
self.changeFrames(self.explode_frames)
|
||||
elif (self.current_time - self.explode_timer) > 500:
|
||||
self.health = 0
|
||||
|
||||
def animation(self):
|
||||
if (self.current_time - self.animate_timer) > self.animate_interval:
|
||||
self.frame_index += 1
|
||||
if self.frame_index >= self.frame_num:
|
||||
self.frame_index = 0
|
||||
self.animate_timer = self.current_time
|
||||
|
||||
image = self.frames[self.frame_index]
|
||||
if self.state == c.IDLE:
|
||||
self.image = pg.transform.rotate(image, self.rotate_degree)
|
||||
else:
|
||||
self.image = image
|
||||
# must keep the center postion of image when rotate
|
||||
self.rect = self.image.get_rect(center=self.init_rect.center)
|
||||
|
||||
def getPosition(self):
|
||||
return (self.rect.centerx, self.orig_y)
|
@ -1,414 +0,0 @@
|
||||
__author__ = 'marble_xu'
|
||||
|
||||
import pygame as pg
|
||||
from .. import tool
|
||||
from .. import constants as c
|
||||
|
||||
class Zombie(pg.sprite.Sprite):
|
||||
def __init__(self, x, y, name, health, head_group=None, damage=1):
|
||||
pg.sprite.Sprite.__init__(self)
|
||||
|
||||
self.name = name
|
||||
self.frames = []
|
||||
self.frame_index = 0
|
||||
self.loadImages()
|
||||
self.frame_num = len(self.frames)
|
||||
|
||||
self.image = self.frames[self.frame_index]
|
||||
self.rect = self.image.get_rect()
|
||||
self.rect.centerx = x
|
||||
self.rect.bottom = y
|
||||
|
||||
self.health = health
|
||||
self.damage = damage
|
||||
self.dead = False
|
||||
self.losHead = False
|
||||
self.helmet = False
|
||||
self.head_group = head_group
|
||||
|
||||
self.walk_timer = 0
|
||||
self.animate_timer = 0
|
||||
self.attack_timer = 0
|
||||
self.state = c.WALK
|
||||
self.animate_interval = 150
|
||||
self.ice_slow_ratio = 1
|
||||
self.ice_slow_timer = 0
|
||||
self.hit_timer = 0
|
||||
self.speed = 1
|
||||
self.freeze_timer = 0
|
||||
self.is_hypno = False # the zombie is hypo and attack other zombies when it ate a HypnoShroom
|
||||
|
||||
def loadFrames(self, frames, name, image_x, colorkey=c.BLACK):
|
||||
frame_list = tool.GFX[name]
|
||||
rect = frame_list[0].get_rect()
|
||||
width, height = rect.w, rect.h
|
||||
width -= image_x
|
||||
|
||||
for frame in frame_list:
|
||||
frames.append(tool.get_image(frame, image_x, 0, width, height, colorkey))
|
||||
|
||||
def update(self, game_info):
|
||||
self.current_time = game_info[c.CURRENT_TIME]
|
||||
self.handleState()
|
||||
self.updateIceSlow()
|
||||
self.animation()
|
||||
|
||||
def handleState(self):
|
||||
if self.state == c.WALK:
|
||||
self.walking()
|
||||
elif self.state == c.ATTACK:
|
||||
self.attacking()
|
||||
elif self.state == c.DIE:
|
||||
self.dying()
|
||||
elif self.state == c.FREEZE:
|
||||
self.freezing()
|
||||
|
||||
def walking(self):
|
||||
if self.health <= 0:
|
||||
self.setDie()
|
||||
elif self.health <= c.LOSTHEAD_HEALTH and not self.losHead:
|
||||
self.changeFrames(self.losthead_walk_frames)
|
||||
self.setLostHead()
|
||||
elif self.health <= c.NORMAL_HEALTH and self.helmet:
|
||||
self.changeFrames(self.walk_frames)
|
||||
self.helmet = False
|
||||
if self.name == c.NEWSPAPER_ZOMBIE:
|
||||
self.speed = 2
|
||||
|
||||
if (self.current_time - self.walk_timer) > (c.ZOMBIE_WALK_INTERVAL * self.getTimeRatio()):
|
||||
self.walk_timer = self.current_time
|
||||
if self.is_hypno:
|
||||
self.rect.x += self.speed
|
||||
else:
|
||||
self.rect.x -= self.speed
|
||||
|
||||
def attacking(self):
|
||||
if self.health <= 0:
|
||||
self.setDie()
|
||||
elif self.health <= c.LOSTHEAD_HEALTH and not self.losHead:
|
||||
self.changeFrames(self.losthead_attack_frames)
|
||||
self.setLostHead()
|
||||
elif self.health <= c.NORMAL_HEALTH and self.helmet:
|
||||
self.changeFrames(self.attack_frames)
|
||||
self.helmet = False
|
||||
if (self.current_time - self.attack_timer) > (c.ATTACK_INTERVAL * self.getTimeRatio()):
|
||||
if self.prey.health > 0:
|
||||
if self.prey_is_plant:
|
||||
self.prey.setDamage(self.damage, self)
|
||||
else:
|
||||
self.prey.setDamage(self.damage)
|
||||
self.attack_timer = self.current_time
|
||||
|
||||
if self.prey.health <= 0:
|
||||
self.prey = None
|
||||
self.setWalk()
|
||||
|
||||
def dying(self):
|
||||
pass
|
||||
|
||||
def freezing(self):
|
||||
if self.health <= 0:
|
||||
self.setDie()
|
||||
elif self.health <= c.LOSTHEAD_HEALTH and not self.losHead:
|
||||
if self.old_state == c.WALK:
|
||||
self.changeFrames(self.losthead_walk_frames)
|
||||
else:
|
||||
self.changeFrames(self.losthead_attack_frames)
|
||||
self.setLostHead()
|
||||
if (self.current_time - self.freeze_timer) > c.FREEZE_TIME:
|
||||
self.setWalk()
|
||||
|
||||
def setLostHead(self):
|
||||
self.losHead = True
|
||||
if self.head_group is not None:
|
||||
self.head_group.add(ZombieHead(self.rect.centerx, self.rect.bottom))
|
||||
|
||||
def changeFrames(self, frames):
|
||||
'''change image frames and modify rect position'''
|
||||
self.frames = frames
|
||||
self.frame_num = len(self.frames)
|
||||
self.frame_index = 0
|
||||
|
||||
bottom = self.rect.bottom
|
||||
centerx = self.rect.centerx
|
||||
self.image = self.frames[self.frame_index]
|
||||
self.rect = self.image.get_rect()
|
||||
self.rect.bottom = bottom
|
||||
self.rect.centerx = centerx
|
||||
|
||||
def animation(self):
|
||||
if self.state == c.FREEZE:
|
||||
self.image.set_alpha(192)
|
||||
return
|
||||
|
||||
if (self.current_time - self.animate_timer) > (self.animate_interval * self.getTimeRatio()):
|
||||
self.frame_index += 1
|
||||
if self.frame_index >= self.frame_num:
|
||||
if self.state == c.DIE:
|
||||
self.kill()
|
||||
return
|
||||
self.frame_index = 0
|
||||
self.animate_timer = self.current_time
|
||||
|
||||
self.image = self.frames[self.frame_index]
|
||||
if self.is_hypno:
|
||||
self.image = pg.transform.flip(self.image, True, False)
|
||||
if(self.current_time - self.hit_timer) >= 200:
|
||||
self.image.set_alpha(255)
|
||||
else:
|
||||
self.image.set_alpha(192)
|
||||
|
||||
def getTimeRatio(self):
|
||||
return self.ice_slow_ratio
|
||||
|
||||
def setIceSlow(self):
|
||||
'''when get a ice bullet damage, slow the attack or walk speed of the zombie'''
|
||||
self.ice_slow_timer = self.current_time
|
||||
self.ice_slow_ratio = 2
|
||||
|
||||
def updateIceSlow(self):
|
||||
if self.ice_slow_ratio > 1:
|
||||
if (self.current_time - self.ice_slow_timer) > c.ICE_SLOW_TIME:
|
||||
self.ice_slow_ratio = 1
|
||||
|
||||
def setDamage(self, damage, ice=False):
|
||||
self.health -= damage
|
||||
self.hit_timer = self.current_time
|
||||
if ice:
|
||||
self.setIceSlow()
|
||||
|
||||
def setWalk(self):
|
||||
self.state = c.WALK
|
||||
self.animate_interval = 150
|
||||
|
||||
if self.helmet:
|
||||
self.changeFrames(self.helmet_walk_frames)
|
||||
elif self.losHead:
|
||||
self.changeFrames(self.losthead_walk_frames)
|
||||
else:
|
||||
self.changeFrames(self.walk_frames)
|
||||
|
||||
def setAttack(self, prey, is_plant=True):
|
||||
self.prey = prey # prey can be plant or other zombies
|
||||
self.prey_is_plant = is_plant
|
||||
self.state = c.ATTACK
|
||||
self.attack_timer = self.current_time
|
||||
self.animate_interval = 100
|
||||
|
||||
if self.helmet:
|
||||
self.changeFrames(self.helmet_attack_frames)
|
||||
elif self.losHead:
|
||||
self.changeFrames(self.losthead_attack_frames)
|
||||
else:
|
||||
self.changeFrames(self.attack_frames)
|
||||
|
||||
def setDie(self):
|
||||
self.state = c.DIE
|
||||
self.animate_interval = 200
|
||||
self.changeFrames(self.die_frames)
|
||||
|
||||
def setBoomDie(self):
|
||||
self.state = c.DIE
|
||||
self.animate_interval = 200
|
||||
self.changeFrames(self.boomdie_frames)
|
||||
|
||||
def setFreeze(self, ice_trap_image):
|
||||
self.old_state = self.state
|
||||
self.state = c.FREEZE
|
||||
self.freeze_timer = self.current_time
|
||||
self.ice_trap_image = ice_trap_image
|
||||
self.ice_trap_rect = ice_trap_image.get_rect()
|
||||
self.ice_trap_rect.centerx = self.rect.centerx
|
||||
self.ice_trap_rect.bottom = self.rect.bottom
|
||||
|
||||
def drawFreezeTrap(self, surface):
|
||||
if self.state == c.FREEZE:
|
||||
surface.blit(self.ice_trap_image, self.ice_trap_rect)
|
||||
|
||||
def setHypno(self):
|
||||
self.is_hypno = True
|
||||
self.setWalk()
|
||||
|
||||
class ZombieHead(Zombie):
|
||||
def __init__(self, x, y):
|
||||
Zombie.__init__(self, x, y, c.ZOMBIE_HEAD, 0)
|
||||
self.state = c.DIE
|
||||
|
||||
def loadImages(self):
|
||||
self.die_frames = []
|
||||
die_name = self.name
|
||||
self.loadFrames(self.die_frames, die_name, 0)
|
||||
self.frames = self.die_frames
|
||||
|
||||
def setWalk(self):
|
||||
self.animate_interval = 100
|
||||
|
||||
class NormalZombie(Zombie):
|
||||
def __init__(self, x, y, head_group):
|
||||
Zombie.__init__(self, x, y, c.NORMAL_ZOMBIE, c.NORMAL_HEALTH, head_group)
|
||||
|
||||
def loadImages(self):
|
||||
self.walk_frames = []
|
||||
self.attack_frames = []
|
||||
self.losthead_walk_frames = []
|
||||
self.losthead_attack_frames = []
|
||||
self.die_frames = []
|
||||
self.boomdie_frames = []
|
||||
|
||||
walk_name = self.name
|
||||
attack_name = self.name + 'Attack'
|
||||
losthead_walk_name = self.name + 'LostHead'
|
||||
losthead_attack_name = self.name + 'LostHeadAttack'
|
||||
die_name = self.name + 'Die'
|
||||
boomdie_name = c.BOOMDIE
|
||||
|
||||
frame_list = [self.walk_frames, self.attack_frames, self.losthead_walk_frames,
|
||||
self.losthead_attack_frames, self.die_frames, self.boomdie_frames]
|
||||
name_list = [walk_name, attack_name, losthead_walk_name,
|
||||
losthead_attack_name, die_name, boomdie_name]
|
||||
|
||||
for i, name in enumerate(name_list):
|
||||
self.loadFrames(frame_list[i], name, tool.ZOMBIE_RECT[name]['x'])
|
||||
|
||||
self.frames = self.walk_frames
|
||||
|
||||
class ConeHeadZombie(Zombie):
|
||||
def __init__(self, x, y, head_group):
|
||||
Zombie.__init__(self, x, y, c.CONEHEAD_ZOMBIE, c.CONEHEAD_HEALTH, head_group)
|
||||
self.helmet = True
|
||||
|
||||
def loadImages(self):
|
||||
self.helmet_walk_frames = []
|
||||
self.helmet_attack_frames = []
|
||||
self.walk_frames = []
|
||||
self.attack_frames = []
|
||||
self.losthead_walk_frames = []
|
||||
self.losthead_attack_frames = []
|
||||
self.die_frames = []
|
||||
self.boomdie_frames = []
|
||||
|
||||
helmet_walk_name = self.name
|
||||
helmet_attack_name = self.name + 'Attack'
|
||||
walk_name = c.NORMAL_ZOMBIE
|
||||
attack_name = c.NORMAL_ZOMBIE + 'Attack'
|
||||
losthead_walk_name = c.NORMAL_ZOMBIE + 'LostHead'
|
||||
losthead_attack_name = c.NORMAL_ZOMBIE + 'LostHeadAttack'
|
||||
die_name = c.NORMAL_ZOMBIE + 'Die'
|
||||
boomdie_name = c.BOOMDIE
|
||||
|
||||
frame_list = [self.helmet_walk_frames, self.helmet_attack_frames,
|
||||
self.walk_frames, self.attack_frames, self.losthead_walk_frames,
|
||||
self.losthead_attack_frames, self.die_frames, self.boomdie_frames]
|
||||
name_list = [helmet_walk_name, helmet_attack_name,
|
||||
walk_name, attack_name, losthead_walk_name,
|
||||
losthead_attack_name, die_name, boomdie_name]
|
||||
|
||||
for i, name in enumerate(name_list):
|
||||
self.loadFrames(frame_list[i], name, tool.ZOMBIE_RECT[name]['x'])
|
||||
|
||||
self.frames = self.helmet_walk_frames
|
||||
|
||||
class BucketHeadZombie(Zombie):
|
||||
def __init__(self, x, y, head_group):
|
||||
Zombie.__init__(self, x, y, c.BUCKETHEAD_ZOMBIE, c.BUCKETHEAD_HEALTH, head_group)
|
||||
self.helmet = True
|
||||
|
||||
def loadImages(self):
|
||||
self.helmet_walk_frames = []
|
||||
self.helmet_attack_frames = []
|
||||
self.walk_frames = []
|
||||
self.attack_frames = []
|
||||
self.losthead_walk_frames = []
|
||||
self.losthead_attack_frames = []
|
||||
self.die_frames = []
|
||||
self.boomdie_frames = []
|
||||
|
||||
helmet_walk_name = self.name
|
||||
helmet_attack_name = self.name + 'Attack'
|
||||
walk_name = c.NORMAL_ZOMBIE
|
||||
attack_name = c.NORMAL_ZOMBIE + 'Attack'
|
||||
losthead_walk_name = c.NORMAL_ZOMBIE + 'LostHead'
|
||||
losthead_attack_name = c.NORMAL_ZOMBIE + 'LostHeadAttack'
|
||||
die_name = c.NORMAL_ZOMBIE + 'Die'
|
||||
boomdie_name = c.BOOMDIE
|
||||
|
||||
frame_list = [self.helmet_walk_frames, self.helmet_attack_frames,
|
||||
self.walk_frames, self.attack_frames, self.losthead_walk_frames,
|
||||
self.losthead_attack_frames, self.die_frames, self.boomdie_frames]
|
||||
name_list = [helmet_walk_name, helmet_attack_name,
|
||||
walk_name, attack_name, losthead_walk_name,
|
||||
losthead_attack_name, die_name, boomdie_name]
|
||||
|
||||
for i, name in enumerate(name_list):
|
||||
self.loadFrames(frame_list[i], name, tool.ZOMBIE_RECT[name]['x'])
|
||||
|
||||
self.frames = self.helmet_walk_frames
|
||||
|
||||
class FlagZombie(Zombie):
|
||||
def __init__(self, x, y, head_group):
|
||||
Zombie.__init__(self, x, y, c.FLAG_ZOMBIE, c.FLAG_HEALTH, head_group)
|
||||
|
||||
def loadImages(self):
|
||||
self.walk_frames = []
|
||||
self.attack_frames = []
|
||||
self.losthead_walk_frames = []
|
||||
self.losthead_attack_frames = []
|
||||
self.die_frames = []
|
||||
self.boomdie_frames = []
|
||||
|
||||
walk_name = self.name
|
||||
attack_name = self.name + 'Attack'
|
||||
losthead_walk_name = self.name + 'LostHead'
|
||||
losthead_attack_name = self.name + 'LostHeadAttack'
|
||||
die_name = c.NORMAL_ZOMBIE + 'Die'
|
||||
boomdie_name = c.BOOMDIE
|
||||
|
||||
frame_list = [self.walk_frames, self.attack_frames, self.losthead_walk_frames,
|
||||
self.losthead_attack_frames, self.die_frames, self.boomdie_frames]
|
||||
name_list = [walk_name, attack_name, losthead_walk_name,
|
||||
losthead_attack_name, die_name, boomdie_name]
|
||||
|
||||
for i, name in enumerate(name_list):
|
||||
self.loadFrames(frame_list[i], name, tool.ZOMBIE_RECT[name]['x'])
|
||||
|
||||
self.frames = self.walk_frames
|
||||
|
||||
class NewspaperZombie(Zombie):
|
||||
def __init__(self, x, y, head_group):
|
||||
Zombie.__init__(self, x, y, c.NEWSPAPER_ZOMBIE, c.NEWSPAPER_HEALTH, head_group)
|
||||
self.helmet = True
|
||||
|
||||
def loadImages(self):
|
||||
self.helmet_walk_frames = []
|
||||
self.helmet_attack_frames = []
|
||||
self.walk_frames = []
|
||||
self.attack_frames = []
|
||||
self.losthead_walk_frames = []
|
||||
self.losthead_attack_frames = []
|
||||
self.die_frames = []
|
||||
self.boomdie_frames = []
|
||||
|
||||
helmet_walk_name = self.name
|
||||
helmet_attack_name = self.name + 'Attack'
|
||||
walk_name = self.name + 'NoPaper'
|
||||
attack_name = self.name + 'NoPaperAttack'
|
||||
losthead_walk_name = self.name + 'LostHead'
|
||||
losthead_attack_name = self.name + 'LostHeadAttack'
|
||||
die_name = self.name + 'Die'
|
||||
boomdie_name = c.BOOMDIE
|
||||
|
||||
frame_list = [self.helmet_walk_frames, self.helmet_attack_frames,
|
||||
self.walk_frames, self.attack_frames, self.losthead_walk_frames,
|
||||
self.losthead_attack_frames, self.die_frames, self.boomdie_frames]
|
||||
name_list = [helmet_walk_name, helmet_attack_name,
|
||||
walk_name, attack_name, losthead_walk_name,
|
||||
losthead_attack_name, die_name, boomdie_name]
|
||||
|
||||
for i, name in enumerate(name_list):
|
||||
if name == c.BOOMDIE:
|
||||
color = c.BLACK
|
||||
else:
|
||||
color = c.WHITE
|
||||
self.loadFrames(frame_list[i], name, tool.ZOMBIE_RECT[name]['x'], color)
|
||||
|
||||
self.frames = self.helmet_walk_frames
|
@ -1,180 +0,0 @@
|
||||
__author__ = 'marble_xu'
|
||||
|
||||
START_LEVEL_NUM = 1
|
||||
|
||||
ORIGINAL_CAPTION = 'Plant VS Zombies Game'
|
||||
|
||||
SCREEN_WIDTH = 800
|
||||
SCREEN_HEIGHT = 600
|
||||
SCREEN_SIZE = (SCREEN_WIDTH, SCREEN_HEIGHT)
|
||||
|
||||
GRID_X_LEN = 9
|
||||
GRID_Y_LEN = 5
|
||||
GRID_X_SIZE = 80
|
||||
GRID_Y_SIZE = 100
|
||||
|
||||
|
||||
WHITE = (255, 255, 255)
|
||||
NAVYBLUE = ( 60, 60, 100)
|
||||
SKY_BLUE = ( 39, 145, 251)
|
||||
BLACK = ( 0, 0, 0)
|
||||
LIGHTYELLOW = (234, 233, 171)
|
||||
RED = (255, 0, 0)
|
||||
PURPLE = (255, 0, 255)
|
||||
GOLD = (255, 215, 0)
|
||||
GREEN = ( 0, 255, 0)
|
||||
|
||||
SIZE_MULTIPLIER = 1.3
|
||||
|
||||
#GAME INFO DICTIONARY KEYS
|
||||
CURRENT_TIME = 'current time'
|
||||
LEVEL_NUM = 'level num'
|
||||
|
||||
#STATES FOR ENTIRE GAME
|
||||
MAIN_MENU = 'main menu'
|
||||
LOAD_SCREEN = 'load screen'
|
||||
GAME_LOSE = 'game los'
|
||||
GAME_VICTORY = 'game victory'
|
||||
LEVEL = 'level'
|
||||
|
||||
MAIN_MENU_IMAGE = 'MainMenu'
|
||||
OPTION_ADVENTURE = 'Adventure'
|
||||
GAME_LOOSE_IMAGE = 'GameLoose'
|
||||
GAME_VICTORY_IMAGE = 'GameVictory'
|
||||
|
||||
#MAP COMPONENTS
|
||||
BACKGROUND_NAME = 'Background'
|
||||
BACKGROUND_TYPE = 'background_type'
|
||||
INIT_SUN_NAME = 'init_sun_value'
|
||||
ZOMBIE_LIST = 'zombie_list'
|
||||
|
||||
MAP_EMPTY = 0
|
||||
MAP_EXIST = 1
|
||||
|
||||
BACKGROUND_OFFSET_X = 220
|
||||
MAP_OFFSET_X = 35
|
||||
MAP_OFFSET_Y = 100
|
||||
|
||||
#MENUBAR
|
||||
CHOOSEBAR_TYPE = 'choosebar_type'
|
||||
CHOOSEBAR_STATIC = 0
|
||||
CHOOSEBAR_MOVE = 1
|
||||
CHOSSEBAR_BOWLING = 2
|
||||
MENUBAR_BACKGROUND = 'ChooserBackground'
|
||||
MOVEBAR_BACKGROUND = 'MoveBackground'
|
||||
PANEL_BACKGROUND = 'PanelBackground'
|
||||
START_BUTTON = 'StartButton'
|
||||
CARD_POOL = 'card_pool'
|
||||
|
||||
MOVEBAR_CARD_FRESH_TIME = 6000
|
||||
CARD_MOVE_TIME = 60
|
||||
|
||||
#PLANT INFO
|
||||
PLANT_IMAGE_RECT = 'plant_image_rect'
|
||||
CAR = 'car'
|
||||
SUN = 'Sun'
|
||||
SUNFLOWER = 'SunFlower'
|
||||
PEASHOOTER = 'Peashooter'
|
||||
SNOWPEASHOOTER = 'SnowPea'
|
||||
WALLNUT = 'WallNut'
|
||||
CHERRYBOMB = 'CherryBomb'
|
||||
THREEPEASHOOTER = 'Threepeater'
|
||||
REPEATERPEA = 'RepeaterPea'
|
||||
CHOMPER = 'Chomper'
|
||||
CHERRY_BOOM_IMAGE = 'Boom'
|
||||
PUFFSHROOM = 'PuffShroom'
|
||||
POTATOMINE = 'PotatoMine'
|
||||
SQUASH = 'Squash'
|
||||
SPIKEWEED = 'Spikeweed'
|
||||
JALAPENO = 'Jalapeno'
|
||||
SCAREDYSHROOM = 'ScaredyShroom'
|
||||
SUNSHROOM = 'SunShroom'
|
||||
ICESHROOM = 'IceShroom'
|
||||
HYPNOSHROOM = 'HypnoShroom'
|
||||
WALLNUTBOWLING = 'WallNutBowling'
|
||||
REDWALLNUTBOWLING = 'RedWallNutBowling'
|
||||
|
||||
PLANT_HEALTH = 5
|
||||
WALLNUT_HEALTH = 30
|
||||
WALLNUT_CRACKED1_HEALTH = 20
|
||||
WALLNUT_CRACKED2_HEALTH = 10
|
||||
WALLNUT_BOWLING_DAMAGE = 10
|
||||
|
||||
PRODUCE_SUN_INTERVAL = 7000
|
||||
FLOWER_SUN_INTERVAL = 22000
|
||||
SUN_LIVE_TIME = 7000
|
||||
SUN_VALUE = 25
|
||||
|
||||
ICE_SLOW_TIME = 2000
|
||||
|
||||
FREEZE_TIME = 7500
|
||||
ICETRAP = 'IceTrap'
|
||||
|
||||
#PLANT CARD INFO
|
||||
CARD_SUNFLOWER = 'card_sunflower'
|
||||
CARD_PEASHOOTER = 'card_peashooter'
|
||||
CARD_SNOWPEASHOOTER = 'card_snowpea'
|
||||
CARD_WALLNUT = 'card_wallnut'
|
||||
CARD_CHERRYBOMB = 'card_cherrybomb'
|
||||
CARD_THREEPEASHOOTER = 'card_threepeashooter'
|
||||
CARD_REPEATERPEA = 'card_repeaterpea'
|
||||
CARD_CHOMPER = 'card_chomper'
|
||||
CARD_PUFFSHROOM = 'card_puffshroom'
|
||||
CARD_POTATOMINE = 'card_potatomine'
|
||||
CARD_SQUASH = 'card_squash'
|
||||
CARD_SPIKEWEED = 'card_spikeweed'
|
||||
CARD_JALAPENO = 'card_jalapeno'
|
||||
CARD_SCAREDYSHROOM = 'card_scaredyshroom'
|
||||
CARD_SUNSHROOM = 'card_sunshroom'
|
||||
CARD_ICESHROOM = 'card_iceshroom'
|
||||
CARD_HYPNOSHROOM = 'card_hypnoshroom'
|
||||
CARD_REDWALLNUT = 'card_redwallnut'
|
||||
|
||||
#BULLET INFO
|
||||
BULLET_PEA = 'PeaNormal'
|
||||
BULLET_PEA_ICE = 'PeaIce'
|
||||
BULLET_MUSHROOM = 'BulletMushRoom'
|
||||
BULLET_DAMAGE_NORMAL = 1
|
||||
|
||||
#ZOMBIE INFO
|
||||
ZOMBIE_IMAGE_RECT = 'zombie_image_rect'
|
||||
ZOMBIE_HEAD = 'ZombieHead'
|
||||
NORMAL_ZOMBIE = 'Zombie'
|
||||
CONEHEAD_ZOMBIE = 'ConeheadZombie'
|
||||
BUCKETHEAD_ZOMBIE = 'BucketheadZombie'
|
||||
FLAG_ZOMBIE = 'FlagZombie'
|
||||
NEWSPAPER_ZOMBIE = 'NewspaperZombie'
|
||||
BOOMDIE = 'BoomDie'
|
||||
|
||||
LOSTHEAD_HEALTH = 5
|
||||
NORMAL_HEALTH = 10
|
||||
FLAG_HEALTH = 15
|
||||
CONEHEAD_HEALTH = 20
|
||||
BUCKETHEAD_HEALTH = 30
|
||||
NEWSPAPER_HEALTH = 15
|
||||
|
||||
ATTACK_INTERVAL = 1000
|
||||
ZOMBIE_WALK_INTERVAL = 70
|
||||
|
||||
ZOMBIE_START_X = SCREEN_WIDTH + 50
|
||||
|
||||
#STATE
|
||||
IDLE = 'idle'
|
||||
FLY = 'fly'
|
||||
EXPLODE = 'explode'
|
||||
ATTACK = 'attack'
|
||||
ATTACKED = 'attacked'
|
||||
DIGEST = 'digest'
|
||||
WALK = 'walk'
|
||||
DIE = 'die'
|
||||
CRY = 'cry'
|
||||
FREEZE = 'freeze'
|
||||
SLEEP = 'sleep'
|
||||
|
||||
#LEVEL STATE
|
||||
CHOOSE = 'choose'
|
||||
PLAY = 'play'
|
||||
|
||||
#BACKGROUND
|
||||
BACKGROUND_DAY = 0
|
||||
BACKGROUND_NIGHT = 1
|
@ -1,14 +0,0 @@
|
||||
{
|
||||
"plant_image_rect":{
|
||||
"PeaNormal":{"x":28, "y":0, "width":28, "height":34},
|
||||
"PeaIce":{"x":26, "y":0, "width":30, "height":34},
|
||||
"Chomper":{"x":0, "y":0, "width":100, "height":114},
|
||||
"PuffShroom":{"x":0, "y":28, "width":35, "height":38},
|
||||
"PuffShroomSleep":{"x":1, "y":0, "width":39, "height":65},
|
||||
"BulletMushRoom":{"x":0, "y":1, "width":55, "height":21},
|
||||
"PotatoMine":{"x":0, "y":0, "width":75, "height":55},
|
||||
"Squash":{"x":10, "y":140, "width":80, "height":86},
|
||||
"SquashAim":{"x":10, "y":140, "width":80, "height":86},
|
||||
"Spikeweed":{"x":3, "y":0, "width":80, "height":35}
|
||||
}
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
{
|
||||
"zombie_image_rect":{
|
||||
"Zombie":{"x":62, "width":90},
|
||||
"ZombieAttack":{"x":62, "width":90},
|
||||
"ZombieLostHead":{"x":62, "width":90},
|
||||
"ZombieLostHeadAttack":{"x":62, "width":90},
|
||||
"ZombieDie":{"x":0, "width":164},
|
||||
"BoomDie":{"x":68, "width":80},
|
||||
"ConeheadZombie":{"x":80, "width":80},
|
||||
"ConeheadZombieAttack":{"x":79, "width":87},
|
||||
"BucketheadZombie":{"x":54, "width":90},
|
||||
"BucketheadZombieAttack":{"x":46, "width":90},
|
||||
"FlagZombie":{"x":56, "width":110},
|
||||
"FlagZombieAttack":{"x":60, "width":100},
|
||||
"FlagZombieLostHead":{"x":55, "width":110},
|
||||
"FlagZombieLostHeadAttack":{"x":55, "width":110},
|
||||
"NewspaperZombie":{"x":48, "width":92},
|
||||
"NewspaperZombieAttack":{"x":48, "width":92},
|
||||
"NewspaperZombieNoPaper":{"x":40, "width":98},
|
||||
"NewspaperZombieNoPaperAttack":{"x":48, "width":92},
|
||||
"NewspaperZombieLostHead":{"x":44, "width":96},
|
||||
"NewspaperZombieLostHeadAttack":{"x":48, "width":92},
|
||||
"NewspaperZombieDie":{"x":0, "width":100}
|
||||
}
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
{
|
||||
"background_type":0,
|
||||
"init_sun_value":500,
|
||||
"zombie_list":[
|
||||
{"time":1000, "map_y":2, "name":"Zombie"}
|
||||
]
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
{
|
||||
"background_type":0,
|
||||
"init_sun_value":50,
|
||||
"zombie_list":[
|
||||
{"time":20000, "map_y":0, "name":"Zombie"},
|
||||
{"time":40000, "map_y":2, "name":"FlagZombie"},
|
||||
{"time":50000, "map_y":4, "name":"Zombie"},
|
||||
{"time":70000, "map_y":3, "name":"Zombie"},
|
||||
{"time":72000, "map_y":1, "name":"FlagZombie"},
|
||||
{"time":74000, "map_y":2, "name":"Zombie"},
|
||||
{"time":90000, "map_y":0, "name":"Zombie"},
|
||||
{"time":91000, "map_y":1, "name":"FlagZombie"},
|
||||
{"time":92000, "map_y":2, "name":"Zombie"},
|
||||
{"time":93000, "map_y":3, "name":"FlagZombie"},
|
||||
{"time":94000, "map_y":0, "name":"Zombie"},
|
||||
{"time":95000, "map_y":4, "name":"FlagZombie"},
|
||||
{"time":96000, "map_y":1, "name":"Zombie"}
|
||||
]
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
{
|
||||
"background_type":0,
|
||||
"init_sun_value":50,
|
||||
"zombie_list":[
|
||||
{"time":20000, "map_y":0, "name":"Zombie"},
|
||||
{"time":40000, "map_y":2, "name":"FlagZombie"},
|
||||
{"time":50000, "map_y":4, "name":"ConeheadZombie"},
|
||||
{"time":70000, "map_y":3, "name":"ConeheadZombie"},
|
||||
{"time":72000, "map_y":1, "name":"FlagZombie"},
|
||||
{"time":74000, "map_y":2, "name":"ConeheadZombie"},
|
||||
{"time":90000, "map_y":0, "name":"FlagZombie"},
|
||||
{"time":91000, "map_y":1, "name":"ConeheadZombie"},
|
||||
{"time":92000, "map_y":2, "name":"Zombie"},
|
||||
{"time":93000, "map_y":3, "name":"ConeheadZombie"},
|
||||
{"time":94000, "map_y":0, "name":"Zombie"},
|
||||
{"time":95000, "map_y":4, "name":"FlagZombie"},
|
||||
{"time":96000, "map_y":1, "name":"ConeheadZombie"}
|
||||
]
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
{
|
||||
"background_type":1,
|
||||
"init_sun_value":50,
|
||||
"zombie_list":[
|
||||
{"time":20000, "map_y":0, "name":"Zombie"},
|
||||
{"time":40000, "map_y":2, "name":"ConeheadZombie"},
|
||||
{"time":50000, "map_y":4, "name":"BucketheadZombie"},
|
||||
{"time":70000, "map_y":3, "name":"BucketheadZombie"},
|
||||
{"time":72000, "map_y":1, "name":"FlagZombie"},
|
||||
{"time":74000, "map_y":2, "name":"ConeheadZombie"},
|
||||
{"time":90000, "map_y":0, "name":"BucketheadZombie"},
|
||||
{"time":91000, "map_y":1, "name":"ConeheadZombie"},
|
||||
{"time":92000, "map_y":2, "name":"Zombie"},
|
||||
{"time":93000, "map_y":3, "name":"BucketheadZombie"},
|
||||
{"time":94000, "map_y":0, "name":"Zombie"},
|
||||
{"time":95000, "map_y":4, "name":"FlagZombie"},
|
||||
{"time":96000, "map_y":1, "name":"BucketheadZombie"},
|
||||
{"time":97000, "map_y":1, "name":"FlagZombie"}
|
||||
]
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
{
|
||||
"background_type":0,
|
||||
"choosebar_type":1,
|
||||
"card_pool":[
|
||||
{"name":"Peashooter"},
|
||||
{"name":"SnowPea"},
|
||||
{"name":"WallNut"},
|
||||
{"name":"CherryBomb"},
|
||||
{"name":"RepeaterPea"},
|
||||
{"name":"Chomper"},
|
||||
{"name":"PotatoMine"}
|
||||
],
|
||||
"zombie_list":[
|
||||
{"time": 1000, "map_y":1, "name":"Zombie"},
|
||||
{"time": 6000, "map_y":3, "name":"FlagZombie"},
|
||||
{"time":10000, "map_y":0, "name":"ConeheadZombie"},
|
||||
{"time":14000, "map_y":2, "name":"NewspaperZombie"},
|
||||
{"time":18000, "map_y":4, "name":"BucketheadZombie"},
|
||||
{"time":22000, "map_y":0, "name":"Zombie"},
|
||||
{"time":26000, "map_y":3, "name":"BucketheadZombie"},
|
||||
{"time":30000, "map_y":4, "name":"Zombie"},
|
||||
{"time":32000, "map_y":3, "name":"NewspaperZombie"},
|
||||
{"time":34000, "map_y":1, "name":"FlagZombie"},
|
||||
{"time":36000, "map_y":2, "name":"ConeheadZombie"},
|
||||
{"time":38000, "map_y":0, "name":"BucketheadZombie"},
|
||||
{"time":40000, "map_y":1, "name":"ConeheadZombie"},
|
||||
{"time":42000, "map_y":1, "name":"NewspaperZombie"},
|
||||
{"time":60000, "map_y":4, "name":"Zombie"},
|
||||
{"time":61000, "map_y":3, "name":"NewspaperZombie"},
|
||||
{"time":62000, "map_y":1, "name":"FlagZombie"},
|
||||
{"time":63000, "map_y":2, "name":"Zombie"},
|
||||
{"time":64000, "map_y":0, "name":"BucketheadZombie"},
|
||||
{"time":65000, "map_y":1, "name":"ConeheadZombie"},
|
||||
{"time":66000, "map_y":2, "name":"Zombie"},
|
||||
{"time":67000, "map_y":4, "name":"BucketheadZombie"},
|
||||
{"time":68000, "map_y":3, "name":"NewspaperZombie"},
|
||||
{"time":69000, "map_y":1, "name":"FlagZombie"},
|
||||
{"time":70000, "map_y":4, "name":"BucketheadZombie"},
|
||||
{"time":71000, "map_y":0, "name":"FlagZombie"}
|
||||
]
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
{
|
||||
"background_type":4,
|
||||
"choosebar_type":2,
|
||||
"card_pool":[
|
||||
{"name":"WallNutBowling"},
|
||||
{"name":"RedWallNutBowling"}
|
||||
],
|
||||
"zombie_list":[
|
||||
{"time": 1000, "map_y":1, "name":"Zombie"},
|
||||
{"time":10000, "map_y":3, "name":"FlagZombie"},
|
||||
{"time":12000, "map_y":0, "name":"ConeheadZombie"},
|
||||
{"time":14000, "map_y":2, "name":"NewspaperZombie"},
|
||||
{"time":18000, "map_y":4, "name":"BucketheadZombie"},
|
||||
{"time":22000, "map_y":3, "name":"Zombie"},
|
||||
{"time":26000, "map_y":1, "name":"BucketheadZombie"},
|
||||
{"time":30000, "map_y":4, "name":"Zombie"},
|
||||
{"time":32000, "map_y":3, "name":"NewspaperZombie"},
|
||||
{"time":34000, "map_y":1, "name":"FlagZombie"},
|
||||
{"time":36000, "map_y":2, "name":"ConeheadZombie"},
|
||||
{"time":40000, "map_y":1, "name":"ConeheadZombie"},
|
||||
{"time":42000, "map_y":1, "name":"NewspaperZombie"},
|
||||
{"time":50000, "map_y":4, "name":"Zombie"},
|
||||
{"time":54000, "map_y":3, "name":"NewspaperZombie"},
|
||||
{"time":58000, "map_y":1, "name":"FlagZombie"},
|
||||
{"time":62000, "map_y":2, "name":"Zombie"},
|
||||
{"time":64000, "map_y":1, "name":"ConeheadZombie"},
|
||||
{"time":66000, "map_y":2, "name":"Zombie"},
|
||||
{"time":68000, "map_y":3, "name":"NewspaperZombie"},
|
||||
{"time":70000, "map_y":1, "name":"FlagZombie"},
|
||||
{"time":72000, "map_y":4, "name":"BucketheadZombie"},
|
||||
{"time":74000, "map_y":0, "name":"FlagZombie"}
|
||||
]
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
__author__ = 'marble_xu'
|
||||
|
||||
from . import tool
|
||||
from . import constants as c
|
||||
from .state import mainmenu, screen, level
|
||||
|
||||
def main():
|
||||
game = tool.Control()
|
||||
state_dict = {c.MAIN_MENU: mainmenu.Menu(),
|
||||
c.GAME_VICTORY: screen.GameVictoryScreen(),
|
||||
c.GAME_LOSE: screen.GameLoseScreen(),
|
||||
c.LEVEL: level.Level()}
|
||||
game.setup_states(state_dict, c.MAIN_MENU)
|
||||
game.main()
|
@ -1,549 +0,0 @@
|
||||
__author__ = 'marble_xu'
|
||||
|
||||
import os
|
||||
import json
|
||||
import pygame as pg
|
||||
from .. import tool
|
||||
from .. import constants as c
|
||||
from ..component import map, plant, zombie, menubar
|
||||
|
||||
class Level(tool.State):
|
||||
def __init__(self):
|
||||
tool.State.__init__(self)
|
||||
|
||||
def startup(self, current_time, persist):
|
||||
self.game_info = persist
|
||||
self.persist = self.game_info
|
||||
self.game_info[c.CURRENT_TIME] = current_time
|
||||
self.map_y_len = c.GRID_Y_LEN
|
||||
self.map = map.Map(c.GRID_X_LEN, self.map_y_len)
|
||||
|
||||
self.loadMap()
|
||||
self.setupBackground()
|
||||
self.initState()
|
||||
|
||||
def loadMap(self):
|
||||
map_file = 'level_' + str(self.game_info[c.LEVEL_NUM]) + '.json'
|
||||
file_path = os.path.join('source', 'data', 'map', map_file)
|
||||
f = open(file_path)
|
||||
self.map_data = json.load(f)
|
||||
f.close()
|
||||
|
||||
def setupBackground(self):
|
||||
img_index = self.map_data[c.BACKGROUND_TYPE]
|
||||
self.background_type = img_index
|
||||
self.background = tool.GFX[c.BACKGROUND_NAME][img_index]
|
||||
self.bg_rect = self.background.get_rect()
|
||||
|
||||
self.level = pg.Surface((self.bg_rect.w, self.bg_rect.h)).convert()
|
||||
self.viewport = tool.SCREEN.get_rect(bottom=self.bg_rect.bottom)
|
||||
self.viewport.x += c.BACKGROUND_OFFSET_X
|
||||
|
||||
def setupGroups(self):
|
||||
self.sun_group = pg.sprite.Group()
|
||||
self.head_group = pg.sprite.Group()
|
||||
|
||||
self.plant_groups = []
|
||||
self.zombie_groups = []
|
||||
self.hypno_zombie_groups = [] #zombies who are hypno after eating hypnoshroom
|
||||
self.bullet_groups = []
|
||||
for i in range(self.map_y_len):
|
||||
self.plant_groups.append(pg.sprite.Group())
|
||||
self.zombie_groups.append(pg.sprite.Group())
|
||||
self.hypno_zombie_groups.append(pg.sprite.Group())
|
||||
self.bullet_groups.append(pg.sprite.Group())
|
||||
|
||||
def setupZombies(self):
|
||||
def takeTime(element):
|
||||
return element[0]
|
||||
|
||||
self.zombie_list = []
|
||||
for data in self.map_data[c.ZOMBIE_LIST]:
|
||||
self.zombie_list.append((data['time'], data['name'], data['map_y']))
|
||||
self.zombie_start_time = 0
|
||||
self.zombie_list.sort(key=takeTime)
|
||||
|
||||
def setupCars(self):
|
||||
self.cars = []
|
||||
for i in range(self.map_y_len):
|
||||
_, y = self.map.getMapGridPos(0, i)
|
||||
self.cars.append(plant.Car(-25, y+20, i))
|
||||
|
||||
def update(self, surface, current_time, mouse_pos, mouse_click):
|
||||
self.current_time = self.game_info[c.CURRENT_TIME] = current_time
|
||||
if self.state == c.CHOOSE:
|
||||
self.choose(mouse_pos, mouse_click)
|
||||
elif self.state == c.PLAY:
|
||||
self.play(mouse_pos, mouse_click)
|
||||
|
||||
self.draw(surface)
|
||||
|
||||
def initBowlingMap(self):
|
||||
print('initBowlingMap')
|
||||
for x in range(3, self.map.width):
|
||||
for y in range(self.map.height):
|
||||
self.map.setMapGridType(x, y, c.MAP_EXIST)
|
||||
|
||||
def initState(self):
|
||||
if c.CHOOSEBAR_TYPE in self.map_data:
|
||||
self.bar_type = self.map_data[c.CHOOSEBAR_TYPE]
|
||||
else:
|
||||
self.bar_type = c.CHOOSEBAR_STATIC
|
||||
|
||||
if self.bar_type == c.CHOOSEBAR_STATIC:
|
||||
self.initChoose()
|
||||
else:
|
||||
card_pool = menubar.getCardPool(self.map_data[c.CARD_POOL])
|
||||
self.initPlay(card_pool)
|
||||
if self.bar_type == c.CHOSSEBAR_BOWLING:
|
||||
self.initBowlingMap()
|
||||
|
||||
def initChoose(self):
|
||||
self.state = c.CHOOSE
|
||||
self.panel = menubar.Panel(menubar.all_card_list, self.map_data[c.INIT_SUN_NAME])
|
||||
|
||||
def choose(self, mouse_pos, mouse_click):
|
||||
if mouse_pos and mouse_click[0]:
|
||||
self.panel.checkCardClick(mouse_pos)
|
||||
if self.panel.checkStartButtonClick(mouse_pos):
|
||||
self.initPlay(self.panel.getSelectedCards())
|
||||
|
||||
def initPlay(self, card_list):
|
||||
self.state = c.PLAY
|
||||
if self.bar_type == c.CHOOSEBAR_STATIC:
|
||||
self.menubar = menubar.MenuBar(card_list, self.map_data[c.INIT_SUN_NAME])
|
||||
else:
|
||||
self.menubar = menubar.MoveBar(card_list)
|
||||
self.drag_plant = False
|
||||
self.hint_image = None
|
||||
self.hint_plant = False
|
||||
if self.background_type == c.BACKGROUND_DAY and self.bar_type == c.CHOOSEBAR_STATIC:
|
||||
self.produce_sun = True
|
||||
else:
|
||||
self.produce_sun = False
|
||||
self.sun_timer = self.current_time
|
||||
|
||||
self.removeMouseImage()
|
||||
self.setupGroups()
|
||||
self.setupZombies()
|
||||
self.setupCars()
|
||||
|
||||
def play(self, mouse_pos, mouse_click):
|
||||
if self.zombie_start_time == 0:
|
||||
self.zombie_start_time = self.current_time
|
||||
elif len(self.zombie_list) > 0:
|
||||
data = self.zombie_list[0]
|
||||
if data[0] <= (self.current_time - self.zombie_start_time):
|
||||
self.createZombie(data[1], data[2])
|
||||
self.zombie_list.remove(data)
|
||||
|
||||
for i in range(self.map_y_len):
|
||||
self.bullet_groups[i].update(self.game_info)
|
||||
self.plant_groups[i].update(self.game_info)
|
||||
self.zombie_groups[i].update(self.game_info)
|
||||
self.hypno_zombie_groups[i].update(self.game_info)
|
||||
for zombie in self.hypno_zombie_groups[i]:
|
||||
if zombie.rect.x > c.SCREEN_WIDTH:
|
||||
zombie.kill()
|
||||
|
||||
self.head_group.update(self.game_info)
|
||||
self.sun_group.update(self.game_info)
|
||||
|
||||
if not self.drag_plant and mouse_pos and mouse_click[0]:
|
||||
result = self.menubar.checkCardClick(mouse_pos)
|
||||
if result:
|
||||
self.setupMouseImage(result[0], result[1])
|
||||
elif self.drag_plant:
|
||||
if mouse_click[1]:
|
||||
self.removeMouseImage()
|
||||
elif mouse_click[0]:
|
||||
if self.menubar.checkMenuBarClick(mouse_pos):
|
||||
self.removeMouseImage()
|
||||
else:
|
||||
self.addPlant()
|
||||
elif mouse_pos is None:
|
||||
self.setupHintImage()
|
||||
|
||||
if self.produce_sun:
|
||||
if(self.current_time - self.sun_timer) > c.PRODUCE_SUN_INTERVAL:
|
||||
self.sun_timer = self.current_time
|
||||
map_x, map_y = self.map.getRandomMapIndex()
|
||||
x, y = self.map.getMapGridPos(map_x, map_y)
|
||||
self.sun_group.add(plant.Sun(x, 0, x, y))
|
||||
if not self.drag_plant and mouse_pos and mouse_click[0]:
|
||||
for sun in self.sun_group:
|
||||
if sun.checkCollision(mouse_pos[0], mouse_pos[1]):
|
||||
self.menubar.increaseSunValue(sun.sun_value)
|
||||
|
||||
for car in self.cars:
|
||||
car.update(self.game_info)
|
||||
|
||||
self.menubar.update(self.current_time)
|
||||
|
||||
self.checkBulletCollisions()
|
||||
self.checkZombieCollisions()
|
||||
self.checkPlants()
|
||||
self.checkCarCollisions()
|
||||
self.checkGameState()
|
||||
|
||||
def createZombie(self, name, map_y):
|
||||
x, y = self.map.getMapGridPos(0, map_y)
|
||||
if name == c.NORMAL_ZOMBIE:
|
||||
self.zombie_groups[map_y].add(zombie.NormalZombie(c.ZOMBIE_START_X, y, self.head_group))
|
||||
elif name == c.CONEHEAD_ZOMBIE:
|
||||
self.zombie_groups[map_y].add(zombie.ConeHeadZombie(c.ZOMBIE_START_X, y, self.head_group))
|
||||
elif name == c.BUCKETHEAD_ZOMBIE:
|
||||
self.zombie_groups[map_y].add(zombie.BucketHeadZombie(c.ZOMBIE_START_X, y, self.head_group))
|
||||
elif name == c.FLAG_ZOMBIE:
|
||||
self.zombie_groups[map_y].add(zombie.FlagZombie(c.ZOMBIE_START_X, y, self.head_group))
|
||||
elif name == c.NEWSPAPER_ZOMBIE:
|
||||
self.zombie_groups[map_y].add(zombie.NewspaperZombie(c.ZOMBIE_START_X, y, self.head_group))
|
||||
|
||||
def canSeedPlant(self):
|
||||
x, y = pg.mouse.get_pos()
|
||||
return self.map.showPlant(x, y)
|
||||
|
||||
def addPlant(self):
|
||||
pos = self.canSeedPlant()
|
||||
if pos is None:
|
||||
return
|
||||
|
||||
if self.hint_image is None:
|
||||
self.setupHintImage()
|
||||
x, y = self.hint_rect.centerx, self.hint_rect.bottom
|
||||
map_x, map_y = self.map.getMapIndex(x, y)
|
||||
if self.plant_name == c.SUNFLOWER:
|
||||
new_plant = plant.SunFlower(x, y, self.sun_group)
|
||||
elif self.plant_name == c.PEASHOOTER:
|
||||
new_plant = plant.PeaShooter(x, y, self.bullet_groups[map_y])
|
||||
elif self.plant_name == c.SNOWPEASHOOTER:
|
||||
new_plant = plant.SnowPeaShooter(x, y, self.bullet_groups[map_y])
|
||||
elif self.plant_name == c.WALLNUT:
|
||||
new_plant = plant.WallNut(x, y)
|
||||
elif self.plant_name == c.CHERRYBOMB:
|
||||
new_plant = plant.CherryBomb(x, y)
|
||||
elif self.plant_name == c.THREEPEASHOOTER:
|
||||
new_plant = plant.ThreePeaShooter(x, y, self.bullet_groups, map_y)
|
||||
elif self.plant_name == c.REPEATERPEA:
|
||||
new_plant = plant.RepeaterPea(x, y, self.bullet_groups[map_y])
|
||||
elif self.plant_name == c.CHOMPER:
|
||||
new_plant = plant.Chomper(x, y)
|
||||
elif self.plant_name == c.PUFFSHROOM:
|
||||
new_plant = plant.PuffShroom(x, y, self.bullet_groups[map_y])
|
||||
elif self.plant_name == c.POTATOMINE:
|
||||
new_plant = plant.PotatoMine(x, y)
|
||||
elif self.plant_name == c.SQUASH:
|
||||
new_plant = plant.Squash(x, y)
|
||||
elif self.plant_name == c.SPIKEWEED:
|
||||
new_plant = plant.Spikeweed(x, y)
|
||||
elif self.plant_name == c.JALAPENO:
|
||||
new_plant = plant.Jalapeno(x, y)
|
||||
elif self.plant_name == c.SCAREDYSHROOM:
|
||||
new_plant = plant.ScaredyShroom(x, y, self.bullet_groups[map_y])
|
||||
elif self.plant_name == c.SUNSHROOM:
|
||||
new_plant = plant.SunShroom(x, y, self.sun_group)
|
||||
elif self.plant_name == c.ICESHROOM:
|
||||
new_plant = plant.IceShroom(x, y)
|
||||
elif self.plant_name == c.HYPNOSHROOM:
|
||||
new_plant = plant.HypnoShroom(x, y)
|
||||
elif self.plant_name == c.WALLNUTBOWLING:
|
||||
new_plant = plant.WallNutBowling(x, y, map_y, self)
|
||||
elif self.plant_name == c.REDWALLNUTBOWLING:
|
||||
new_plant = plant.RedWallNutBowling(x, y)
|
||||
|
||||
if new_plant.can_sleep and self.background_type == c.BACKGROUND_DAY:
|
||||
new_plant.setSleep()
|
||||
self.plant_groups[map_y].add(new_plant)
|
||||
if self.bar_type == c.CHOOSEBAR_STATIC:
|
||||
self.menubar.decreaseSunValue(self.select_plant.sun_cost)
|
||||
self.menubar.setCardFrozenTime(self.plant_name)
|
||||
else:
|
||||
self.menubar.deleateCard(self.select_plant)
|
||||
|
||||
if self.bar_type != c.CHOSSEBAR_BOWLING:
|
||||
self.map.setMapGridType(map_x, map_y, c.MAP_EXIST)
|
||||
self.removeMouseImage()
|
||||
#print('addPlant map[%d,%d], grid pos[%d, %d] pos[%d, %d]' % (map_x, map_y, x, y, pos[0], pos[1]))
|
||||
|
||||
def setupHintImage(self):
|
||||
pos = self.canSeedPlant()
|
||||
if pos and self.mouse_image:
|
||||
if (self.hint_image and pos[0] == self.hint_rect.x and
|
||||
pos[1] == self.hint_rect.y):
|
||||
return
|
||||
width, height = self.mouse_rect.w, self.mouse_rect.h
|
||||
image = pg.Surface([width, height])
|
||||
image.blit(self.mouse_image, (0, 0), (0, 0, width, height))
|
||||
image.set_colorkey(c.BLACK)
|
||||
image.set_alpha(128)
|
||||
self.hint_image = image
|
||||
self.hint_rect = image.get_rect()
|
||||
self.hint_rect.centerx = pos[0]
|
||||
self.hint_rect.bottom = pos[1]
|
||||
self.hint_plant = True
|
||||
else:
|
||||
self.hint_plant = False
|
||||
|
||||
def setupMouseImage(self, plant_name, select_plant):
|
||||
frame_list = tool.GFX[plant_name]
|
||||
if plant_name in tool.PLANT_RECT:
|
||||
data = tool.PLANT_RECT[plant_name]
|
||||
x, y, width, height = data['x'], data['y'], data['width'], data['height']
|
||||
else:
|
||||
x, y = 0, 0
|
||||
rect = frame_list[0].get_rect()
|
||||
width, height = rect.w, rect.h
|
||||
|
||||
if (plant_name == c.POTATOMINE or plant_name == c.SQUASH or
|
||||
plant_name == c.SPIKEWEED or plant_name == c.JALAPENO or
|
||||
plant_name == c.SCAREDYSHROOM or plant_name == c.SUNSHROOM or
|
||||
plant_name == c.ICESHROOM or plant_name == c.HYPNOSHROOM or
|
||||
plant_name == c.WALLNUTBOWLING or plant_name == c.REDWALLNUTBOWLING):
|
||||
color = c.WHITE
|
||||
else:
|
||||
color = c.BLACK
|
||||
self.mouse_image = tool.get_image(frame_list[0], x, y, width, height, color, 1)
|
||||
self.mouse_rect = self.mouse_image.get_rect()
|
||||
pg.mouse.set_visible(False)
|
||||
self.drag_plant = True
|
||||
self.plant_name = plant_name
|
||||
self.select_plant = select_plant
|
||||
|
||||
def removeMouseImage(self):
|
||||
pg.mouse.set_visible(True)
|
||||
self.drag_plant = False
|
||||
self.mouse_image = None
|
||||
self.hint_image = None
|
||||
self.hint_plant = False
|
||||
|
||||
def checkBulletCollisions(self):
|
||||
collided_func = pg.sprite.collide_circle_ratio(0.7)
|
||||
for i in range(self.map_y_len):
|
||||
for bullet in self.bullet_groups[i]:
|
||||
if bullet.state == c.FLY:
|
||||
zombie = pg.sprite.spritecollideany(bullet, self.zombie_groups[i], collided_func)
|
||||
if zombie and zombie.state != c.DIE:
|
||||
zombie.setDamage(bullet.damage, bullet.ice)
|
||||
bullet.setExplode()
|
||||
|
||||
def checkZombieCollisions(self):
|
||||
if self.bar_type == c.CHOSSEBAR_BOWLING:
|
||||
ratio = 0.6
|
||||
else:
|
||||
ratio = 0.7
|
||||
collided_func = pg.sprite.collide_circle_ratio(ratio)
|
||||
for i in range(self.map_y_len):
|
||||
hypo_zombies = []
|
||||
for zombie in self.zombie_groups[i]:
|
||||
if zombie.state != c.WALK:
|
||||
continue
|
||||
plant = pg.sprite.spritecollideany(zombie, self.plant_groups[i], collided_func)
|
||||
if plant:
|
||||
if plant.name == c.WALLNUTBOWLING:
|
||||
if plant.canHit(i):
|
||||
zombie.setDamage(c.WALLNUT_BOWLING_DAMAGE)
|
||||
plant.changeDirection(i)
|
||||
elif plant.name == c.REDWALLNUTBOWLING:
|
||||
if plant.state == c.IDLE:
|
||||
plant.setAttack()
|
||||
elif plant.name != c.SPIKEWEED:
|
||||
zombie.setAttack(plant)
|
||||
|
||||
for hypno_zombie in self.hypno_zombie_groups[i]:
|
||||
if hypno_zombie.health <= 0:
|
||||
continue
|
||||
zombie_list = pg.sprite.spritecollide(hypno_zombie,
|
||||
self.zombie_groups[i], False,collided_func)
|
||||
for zombie in zombie_list:
|
||||
if zombie.state == c.DIE:
|
||||
continue
|
||||
if zombie.state == c.WALK:
|
||||
zombie.setAttack(hypno_zombie, False)
|
||||
if hypno_zombie.state == c.WALK:
|
||||
hypno_zombie.setAttack(zombie, False)
|
||||
|
||||
def checkCarCollisions(self):
|
||||
collided_func = pg.sprite.collide_circle_ratio(0.8)
|
||||
for car in self.cars:
|
||||
zombies = pg.sprite.spritecollide(car, self.zombie_groups[car.map_y], False, collided_func)
|
||||
for zombie in zombies:
|
||||
if zombie and zombie.state != c.DIE:
|
||||
car.setWalk()
|
||||
zombie.setDie()
|
||||
if car.dead:
|
||||
self.cars.remove(car)
|
||||
|
||||
def boomZombies(self, x, map_y, y_range, x_range):
|
||||
for i in range(self.map_y_len):
|
||||
if abs(i - map_y) > y_range:
|
||||
continue
|
||||
for zombie in self.zombie_groups[i]:
|
||||
if abs(zombie.rect.centerx - x) <= x_range:
|
||||
zombie.setBoomDie()
|
||||
|
||||
def freezeZombies(self, plant):
|
||||
for i in range(self.map_y_len):
|
||||
for zombie in self.zombie_groups[i]:
|
||||
if zombie.rect.centerx < c.SCREEN_WIDTH:
|
||||
zombie.setFreeze(plant.trap_frames[0])
|
||||
|
||||
def killPlant(self, plant):
|
||||
x, y = plant.getPosition()
|
||||
map_x, map_y = self.map.getMapIndex(x, y)
|
||||
if self.bar_type != c.CHOSSEBAR_BOWLING:
|
||||
self.map.setMapGridType(map_x, map_y, c.MAP_EMPTY)
|
||||
if (plant.name == c.CHERRYBOMB or plant.name == c.JALAPENO or
|
||||
(plant.name == c.POTATOMINE and not plant.is_init) or
|
||||
plant.name == c.REDWALLNUTBOWLING):
|
||||
self.boomZombies(plant.rect.centerx, map_y, plant.explode_y_range,
|
||||
plant.explode_x_range)
|
||||
elif plant.name == c.ICESHROOM and plant.state != c.SLEEP:
|
||||
self.freezeZombies(plant)
|
||||
elif plant.name == c.HYPNOSHROOM and plant.state != c.SLEEP:
|
||||
zombie = plant.kill_zombie
|
||||
zombie.setHypno()
|
||||
_, map_y = self.map.getMapIndex(zombie.rect.centerx, zombie.rect.bottom)
|
||||
self.zombie_groups[map_y].remove(zombie)
|
||||
self.hypno_zombie_groups[map_y].add(zombie)
|
||||
plant.kill()
|
||||
|
||||
def checkPlant(self, plant, i):
|
||||
zombie_len = len(self.zombie_groups[i])
|
||||
if plant.name == c.THREEPEASHOOTER:
|
||||
if plant.state == c.IDLE:
|
||||
if zombie_len > 0:
|
||||
plant.setAttack()
|
||||
elif (i-1) >= 0 and len(self.zombie_groups[i-1]) > 0:
|
||||
plant.setAttack()
|
||||
elif (i+1) < self.map_y_len and len(self.zombie_groups[i+1]) > 0:
|
||||
plant.setAttack()
|
||||
elif plant.state == c.ATTACK:
|
||||
if zombie_len > 0:
|
||||
pass
|
||||
elif (i-1) >= 0 and len(self.zombie_groups[i-1]) > 0:
|
||||
pass
|
||||
elif (i+1) < self.map_y_len and len(self.zombie_groups[i+1]) > 0:
|
||||
pass
|
||||
else:
|
||||
plant.setIdle()
|
||||
elif plant.name == c.CHOMPER:
|
||||
for zombie in self.zombie_groups[i]:
|
||||
if plant.canAttack(zombie):
|
||||
plant.setAttack(zombie, self.zombie_groups[i])
|
||||
break
|
||||
elif plant.name == c.POTATOMINE:
|
||||
for zombie in self.zombie_groups[i]:
|
||||
if plant.canAttack(zombie):
|
||||
plant.setAttack()
|
||||
break
|
||||
elif plant.name == c.SQUASH:
|
||||
for zombie in self.zombie_groups[i]:
|
||||
if plant.canAttack(zombie):
|
||||
plant.setAttack(zombie, self.zombie_groups[i])
|
||||
break
|
||||
elif plant.name == c.SPIKEWEED:
|
||||
can_attack = False
|
||||
for zombie in self.zombie_groups[i]:
|
||||
if plant.canAttack(zombie):
|
||||
can_attack = True
|
||||
break
|
||||
if plant.state == c.IDLE and can_attack:
|
||||
plant.setAttack(self.zombie_groups[i])
|
||||
elif plant.state == c.ATTACK and not can_attack:
|
||||
plant.setIdle()
|
||||
elif plant.name == c.SCAREDYSHROOM:
|
||||
need_cry = False
|
||||
can_attack = False
|
||||
for zombie in self.zombie_groups[i]:
|
||||
if plant.needCry(zombie):
|
||||
need_cry = True
|
||||
break
|
||||
elif plant.canAttack(zombie):
|
||||
can_attack = True
|
||||
if need_cry:
|
||||
if plant.state != c.CRY:
|
||||
plant.setCry()
|
||||
elif can_attack:
|
||||
if plant.state != c.ATTACK:
|
||||
plant.setAttack()
|
||||
elif plant.state != c.IDLE:
|
||||
plant.setIdle()
|
||||
elif(plant.name == c.WALLNUTBOWLING or
|
||||
plant.name == c.REDWALLNUTBOWLING):
|
||||
pass
|
||||
else:
|
||||
can_attack = False
|
||||
if (plant.state == c.IDLE and zombie_len > 0):
|
||||
for zombie in self.zombie_groups[i]:
|
||||
if plant.canAttack(zombie):
|
||||
can_attack = True
|
||||
break
|
||||
if plant.state == c.IDLE and can_attack:
|
||||
plant.setAttack()
|
||||
elif (plant.state == c.ATTACK and not can_attack):
|
||||
plant.setIdle()
|
||||
|
||||
def checkPlants(self):
|
||||
for i in range(self.map_y_len):
|
||||
for plant in self.plant_groups[i]:
|
||||
if plant.state != c.SLEEP:
|
||||
self.checkPlant(plant, i)
|
||||
if plant.health <= 0:
|
||||
self.killPlant(plant)
|
||||
|
||||
def checkVictory(self):
|
||||
if len(self.zombie_list) > 0:
|
||||
return False
|
||||
for i in range(self.map_y_len):
|
||||
if len(self.zombie_groups[i]) > 0:
|
||||
return False
|
||||
return True
|
||||
|
||||
def checkLose(self):
|
||||
for i in range(self.map_y_len):
|
||||
for zombie in self.zombie_groups[i]:
|
||||
if zombie.rect.right < 0:
|
||||
return True
|
||||
return False
|
||||
|
||||
def checkGameState(self):
|
||||
if self.checkVictory():
|
||||
self.game_info[c.LEVEL_NUM] += 1
|
||||
self.next = c.GAME_VICTORY
|
||||
self.done = True
|
||||
elif self.checkLose():
|
||||
self.next = c.GAME_LOSE
|
||||
self.done = True
|
||||
|
||||
def drawMouseShow(self, surface):
|
||||
if self.hint_plant:
|
||||
surface.blit(self.hint_image, self.hint_rect)
|
||||
x, y = pg.mouse.get_pos()
|
||||
self.mouse_rect.centerx = x
|
||||
self.mouse_rect.centery = y
|
||||
surface.blit(self.mouse_image, self.mouse_rect)
|
||||
|
||||
def drawZombieFreezeTrap(self, i, surface):
|
||||
for zombie in self.zombie_groups[i]:
|
||||
zombie.drawFreezeTrap(surface)
|
||||
|
||||
def draw(self, surface):
|
||||
self.level.blit(self.background, self.viewport, self.viewport)
|
||||
surface.blit(self.level, (0,0), self.viewport)
|
||||
if self.state == c.CHOOSE:
|
||||
self.panel.draw(surface)
|
||||
elif self.state == c.PLAY:
|
||||
self.menubar.draw(surface)
|
||||
for i in range(self.map_y_len):
|
||||
self.plant_groups[i].draw(surface)
|
||||
self.zombie_groups[i].draw(surface)
|
||||
self.hypno_zombie_groups[i].draw(surface)
|
||||
self.bullet_groups[i].draw(surface)
|
||||
self.drawZombieFreezeTrap(i, surface)
|
||||
for car in self.cars:
|
||||
car.draw(surface)
|
||||
self.head_group.draw(surface)
|
||||
self.sun_group.draw(surface)
|
||||
|
||||
if self.drag_plant:
|
||||
self.drawMouseShow(surface)
|
@ -1,69 +0,0 @@
|
||||
__author__ = 'marble_xu'
|
||||
|
||||
import pygame as pg
|
||||
from .. import tool
|
||||
from .. import constants as c
|
||||
|
||||
class Menu(tool.State):
|
||||
def __init__(self):
|
||||
tool.State.__init__(self)
|
||||
|
||||
def startup(self, current_time, persist):
|
||||
self.next = c.LEVEL
|
||||
self.persist = persist
|
||||
self.game_info = persist
|
||||
|
||||
self.setupBackground()
|
||||
self.setupOption()
|
||||
|
||||
def setupBackground(self):
|
||||
frame_rect = [80, 0, 800, 600]
|
||||
self.bg_image = tool.get_image(tool.GFX[c.MAIN_MENU_IMAGE], *frame_rect)
|
||||
self.bg_rect = self.bg_image.get_rect()
|
||||
self.bg_rect.x = 0
|
||||
self.bg_rect.y = 0
|
||||
|
||||
def setupOption(self):
|
||||
self.option_frames = []
|
||||
frame_names = [c.OPTION_ADVENTURE + '_0', c.OPTION_ADVENTURE + '_1']
|
||||
frame_rect = [0, 0, 165, 77]
|
||||
|
||||
for name in frame_names:
|
||||
self.option_frames.append(tool.get_image(tool.GFX[name], *frame_rect, c.BLACK, 1.7))
|
||||
|
||||
self.option_frame_index = 0
|
||||
self.option_image = self.option_frames[self.option_frame_index]
|
||||
self.option_rect = self.option_image.get_rect()
|
||||
self.option_rect.x = 435
|
||||
self.option_rect.y = 75
|
||||
|
||||
self.option_start = 0
|
||||
self.option_timer = 0
|
||||
self.option_clicked = False
|
||||
|
||||
def checkOptionClick(self, mouse_pos):
|
||||
x, y = mouse_pos
|
||||
if(x >= self.option_rect.x and x <= self.option_rect.right and
|
||||
y >= self.option_rect.y and y <= self.option_rect.bottom):
|
||||
self.option_clicked = True
|
||||
self.option_timer = self.option_start = self.current_time
|
||||
return False
|
||||
|
||||
def update(self, surface, current_time, mouse_pos, mouse_click):
|
||||
self.current_time = self.game_info[c.CURRENT_TIME] = current_time
|
||||
|
||||
if not self.option_clicked:
|
||||
if mouse_pos:
|
||||
self.checkOptionClick(mouse_pos)
|
||||
else:
|
||||
if(self.current_time - self.option_timer) > 200:
|
||||
self.option_frame_index += 1
|
||||
if self.option_frame_index >= 2:
|
||||
self.option_frame_index = 0
|
||||
self.option_timer = self.current_time
|
||||
self.option_image = self.option_frames[self.option_frame_index]
|
||||
if(self.current_time - self.option_start) > 1300:
|
||||
self.done = True
|
||||
|
||||
surface.blit(self.bg_image, self.bg_rect)
|
||||
surface.blit(self.option_image, self.option_rect)
|
@ -1,59 +0,0 @@
|
||||
__author__ = 'marble_xu'
|
||||
|
||||
import pygame as pg
|
||||
from .. import tool
|
||||
from .. import constants as c
|
||||
|
||||
class Screen(tool.State):
|
||||
def __init__(self):
|
||||
tool.State.__init__(self)
|
||||
self.end_time = 3000
|
||||
|
||||
def startup(self, current_time, persist):
|
||||
self.start_time = current_time
|
||||
self.next = c.LEVEL
|
||||
self.persist = persist
|
||||
self.game_info = persist
|
||||
name = self.getImageName()
|
||||
self.setupImage(name)
|
||||
self.next = self.set_next_state()
|
||||
|
||||
def getImageName(self):
|
||||
pass
|
||||
|
||||
def set_next_state(self):
|
||||
pass
|
||||
|
||||
def setupImage(self, name):
|
||||
frame_rect = [0, 0, 800, 600]
|
||||
self.image = tool.get_image(tool.GFX[name], *frame_rect)
|
||||
self.rect = self.image.get_rect()
|
||||
self.rect.x = 0
|
||||
self.rect.y = 0
|
||||
|
||||
def update(self, surface, current_time, mouse_pos, mouse_click):
|
||||
if(current_time - self.start_time) < self.end_time:
|
||||
surface.fill(c.WHITE)
|
||||
surface.blit(self.image, self.rect)
|
||||
else:
|
||||
self.done = True
|
||||
|
||||
class GameVictoryScreen(Screen):
|
||||
def __init__(self):
|
||||
Screen.__init__(self)
|
||||
|
||||
def getImageName(self):
|
||||
return c.GAME_VICTORY_IMAGE
|
||||
|
||||
def set_next_state(self):
|
||||
return c.LEVEL
|
||||
|
||||
class GameLoseScreen(Screen):
|
||||
def __init__(self):
|
||||
Screen.__init__(self)
|
||||
|
||||
def getImageName(self):
|
||||
return c.GAME_LOOSE_IMAGE
|
||||
|
||||
def set_next_state(self):
|
||||
return c.MAIN_MENU
|
@ -1,176 +0,0 @@
|
||||
__author__ = 'marble_xu'
|
||||
|
||||
import os
|
||||
import json
|
||||
from abc import abstractmethod
|
||||
import pygame as pg
|
||||
from . import constants as c
|
||||
|
||||
class State():
|
||||
def __init__(self):
|
||||
self.start_time = 0.0
|
||||
self.current_time = 0.0
|
||||
self.done = False
|
||||
self.next = None
|
||||
self.persist = {}
|
||||
|
||||
@abstractmethod
|
||||
def startup(self, current_time, persist):
|
||||
'''abstract method'''
|
||||
|
||||
def cleanup(self):
|
||||
self.done = False
|
||||
return self.persist
|
||||
|
||||
@abstractmethod
|
||||
def update(self, surface, keys, current_time):
|
||||
'''abstract method'''
|
||||
|
||||
class Control():
|
||||
def __init__(self):
|
||||
self.screen = pg.display.get_surface()
|
||||
self.done = False
|
||||
self.clock = pg.time.Clock()
|
||||
self.fps = 60
|
||||
self.keys = pg.key.get_pressed()
|
||||
self.mouse_pos = None
|
||||
self.mouse_click = [False, False] # value:[left mouse click, right mouse click]
|
||||
self.current_time = 0.0
|
||||
self.state_dict = {}
|
||||
self.state_name = None
|
||||
self.state = None
|
||||
self.game_info = {c.CURRENT_TIME:0.0,
|
||||
c.LEVEL_NUM:c.START_LEVEL_NUM}
|
||||
|
||||
def setup_states(self, state_dict, start_state):
|
||||
self.state_dict = state_dict
|
||||
self.state_name = start_state
|
||||
self.state = self.state_dict[self.state_name]
|
||||
self.state.startup(self.current_time, self.game_info)
|
||||
|
||||
def update(self):
|
||||
self.current_time = pg.time.get_ticks()
|
||||
if self.state.done:
|
||||
self.flip_state()
|
||||
self.state.update(self.screen, self.current_time, self.mouse_pos, self.mouse_click)
|
||||
self.mouse_pos = None
|
||||
self.mouse_click[0] = False
|
||||
self.mouse_click[1] = False
|
||||
|
||||
def flip_state(self):
|
||||
previous, self.state_name = self.state_name, self.state.next
|
||||
persist = self.state.cleanup()
|
||||
self.state = self.state_dict[self.state_name]
|
||||
self.state.startup(self.current_time, persist)
|
||||
|
||||
def event_loop(self):
|
||||
for event in pg.event.get():
|
||||
if event.type == pg.QUIT:
|
||||
self.done = True
|
||||
elif event.type == pg.KEYDOWN:
|
||||
self.keys = pg.key.get_pressed()
|
||||
elif event.type == pg.KEYUP:
|
||||
self.keys = pg.key.get_pressed()
|
||||
elif event.type == pg.MOUSEBUTTONDOWN:
|
||||
self.mouse_pos = pg.mouse.get_pos()
|
||||
self.mouse_click[0], _, self.mouse_click[1] = pg.mouse.get_pressed()
|
||||
print('pos:', self.mouse_pos, ' mouse:', self.mouse_click)
|
||||
|
||||
def main(self):
|
||||
while not self.done:
|
||||
self.event_loop()
|
||||
self.update()
|
||||
pg.display.update()
|
||||
self.clock.tick(self.fps)
|
||||
print('game over')
|
||||
|
||||
def get_image(sheet, x, y, width, height, colorkey=c.BLACK, scale=1):
|
||||
image = pg.Surface([width, height])
|
||||
rect = image.get_rect()
|
||||
|
||||
image.blit(sheet, (0, 0), (x, y, width, height))
|
||||
image.set_colorkey(colorkey)
|
||||
image = pg.transform.scale(image,
|
||||
(int(rect.width*scale),
|
||||
int(rect.height*scale)))
|
||||
return image
|
||||
|
||||
def load_image_frames(directory, image_name, colorkey, accept):
|
||||
frame_list = []
|
||||
tmp = {}
|
||||
# image_name is "Peashooter", pic name is 'Peashooter_1', get the index 1
|
||||
index_start = len(image_name) + 1
|
||||
frame_num = 0;
|
||||
for pic in os.listdir(directory):
|
||||
name, ext = os.path.splitext(pic)
|
||||
if ext.lower() in accept:
|
||||
index = int(name[index_start:])
|
||||
img = pg.image.load(os.path.join(directory, pic))
|
||||
if img.get_alpha():
|
||||
img = img.convert_alpha()
|
||||
else:
|
||||
img = img.convert()
|
||||
img.set_colorkey(colorkey)
|
||||
tmp[index]= img
|
||||
frame_num += 1
|
||||
|
||||
for i in range(frame_num):
|
||||
frame_list.append(tmp[i])
|
||||
return frame_list
|
||||
|
||||
def load_all_gfx(directory, colorkey=c.WHITE, accept=('.png', '.jpg', '.bmp', '.gif')):
|
||||
graphics = {}
|
||||
for name1 in os.listdir(directory):
|
||||
# subfolders under the folder resources\graphics
|
||||
dir1 = os.path.join(directory, name1)
|
||||
if os.path.isdir(dir1):
|
||||
for name2 in os.listdir(dir1):
|
||||
dir2 = os.path.join(dir1, name2)
|
||||
if os.path.isdir(dir2):
|
||||
# e.g. subfolders under the folder resources\graphics\Zombies
|
||||
for name3 in os.listdir(dir2):
|
||||
dir3 = os.path.join(dir2, name3)
|
||||
# e.g. subfolders or pics under the folder resources\graphics\Zombies\ConeheadZombie
|
||||
if os.path.isdir(dir3):
|
||||
# e.g. it's the folder resources\graphics\Zombies\ConeheadZombie\ConeheadZombieAttack
|
||||
image_name, _ = os.path.splitext(name3)
|
||||
graphics[image_name] = load_image_frames(dir3, image_name, colorkey, accept)
|
||||
else:
|
||||
# e.g. pics under the folder resources\graphics\Plants\Peashooter
|
||||
image_name, _ = os.path.splitext(name2)
|
||||
graphics[image_name] = load_image_frames(dir2, image_name, colorkey, accept)
|
||||
break
|
||||
else:
|
||||
# e.g. pics under the folder resources\graphics\Screen
|
||||
name, ext = os.path.splitext(name2)
|
||||
if ext.lower() in accept:
|
||||
img = pg.image.load(dir2)
|
||||
if img.get_alpha():
|
||||
img = img.convert_alpha()
|
||||
else:
|
||||
img = img.convert()
|
||||
img.set_colorkey(colorkey)
|
||||
graphics[name] = img
|
||||
return graphics
|
||||
|
||||
def loadZombieImageRect():
|
||||
file_path = os.path.join('source', 'data', 'entity', 'zombie.json')
|
||||
f = open(file_path)
|
||||
data = json.load(f)
|
||||
f.close()
|
||||
return data[c.ZOMBIE_IMAGE_RECT]
|
||||
|
||||
def loadPlantImageRect():
|
||||
file_path = os.path.join('source', 'data', 'entity', 'plant.json')
|
||||
f = open(file_path)
|
||||
data = json.load(f)
|
||||
f.close()
|
||||
return data[c.PLANT_IMAGE_RECT]
|
||||
|
||||
pg.init()
|
||||
pg.display.set_caption(c.ORIGINAL_CAPTION)
|
||||
SCREEN = pg.display.set_mode(c.SCREEN_SIZE)
|
||||
|
||||
GFX = load_all_gfx(os.path.join("resources","graphics"))
|
||||
ZOMBIE_RECT = loadZombieImageRect()
|
||||
PLANT_RECT = loadPlantImageRect()
|
Loading…
Reference in new issue