parent
5969c3c7ca
commit
58bc70c436
@ -0,0 +1,45 @@
|
|||||||
|
__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
|
@ -0,0 +1,441 @@
|
|||||||
|
__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)
|
@ -0,0 +1,971 @@
|
|||||||
|
__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)
|
@ -0,0 +1,414 @@
|
|||||||
|
__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
|
@ -0,0 +1,180 @@
|
|||||||
|
__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
|
@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"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}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"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}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"background_type":0,
|
||||||
|
"init_sun_value":500,
|
||||||
|
"zombie_list":[
|
||||||
|
{"time":1000, "map_y":2, "name":"Zombie"}
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"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"}
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"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"}
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"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"}
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
{
|
||||||
|
"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"}
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
{
|
||||||
|
"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"}
|
||||||
|
]
|
||||||
|
}
|
Loading…
Reference in new issue