juegos-python/Battles/Code/Maps.py

806 lines
30 KiB
Python
Raw Permalink Normal View History

2023-04-10 00:48:44 +02:00
"""
~~~~~~~
Maps.py
~~~~~~~
By - JATIN KUMAR MANDAV
This library contains the MAPS class which contains major;y two function, openMap() and createMap()
The user can open the predefined or their saved custom maps using openMap() or
Can save their oen designed custom maps using createMap()
This is completely coded using PYGAME library of PYTHON 2.7
Lines - 809
"""
# Imports
import pygame
import sys
from math import *
from GUI import *
from Structures import *
from Troops import *
width = 0
height = 0
display = None
margin = 0
clock = pygame.time.Clock()
groundW = 0
groundH = 0
validW = 0
validH = 0
margin2 = 0
white = (255, 255, 255)
black = (0, 0, 0)
yellow = (241, 196, 15)
red = (203, 67, 53)
green = (30, 132, 73)
blue = (36, 113, 163)
gray = (113, 125, 126)
darkGray = (23, 32, 42)
activeButton = 1
presentLevel = 1
victory = False
stars = 0
canInfo = {"w":10, "h":33, "size":33, "range":200, "baseR":25, "shotR":7,
"shotSpeed":5}
mortarInfo = {"w": 25, "h":25, "r":50, "range":300, "shotR":7, "shotSpeed":7}
towerInfo = {"w": 5, "h":30, "size":20, "range":300, "baseR":25, "shotR":7,
"shotSpeed":10}
hqInfo = {"r":50}
def initMaps(screen, size, border=0, border2=0):
global width, height, display, margin, groundW, groundH, validW, validH, margin2
display = screen
width = size[0]
height = size[1]
margin = border
groundW = width - 150 - 2*margin
groundH = height - 2*margin
margin2 = border2
validW = width - 2*margin2 - 150
validH = height - 2*margin2
initGUI(display, (width, height))
initStruct(display, (groundW, groundH), margin)
initTroops(display, (groundW, groundH), margin)
def active(num):
global activeButton
activeButton = num
def levelActive(num):
global presentLevel
presentLevel = num
# Saves the custom maps created by user or "guest"
def saveMap(defenceStruct, user="guest"):
global structure, noCannon, noMortar, noTower, noHquart, noResource
if len(defenceStruct) > 0:
noCannon = 0
noMortar = 0
noTower = 0
noHquart = 0
noResource = 0
cannons = []
mortars = []
towers = []
headquarter = []
resources = []
for struct in defenceStruct:
if struct.type == "CANNON":
cannons.append(struct)
elif struct.type == "MORTAR":
mortars.append(struct)
elif struct.type == "TOWER":
towers.append(struct)
elif struct.type == "HEADQUARTERS":
headquarter.append(struct)
elif struct.type == "RESOURCE":
resources.append(struct)
if user == "admin":
fmap = open("Data/maps", "a")
else:
fmap = open("Data/customMaps", "a")
for struct in cannons:
fmap.write(str(struct.x) + "," + str(struct.y) + "," + str(struct.level) + "/")
fmap.write("|")
for struct in mortars:
fmap.write(str(struct.x) + "," + str(struct.y) + "," + str(struct.level) + "/")
fmap.write("|")
for struct in towers:
fmap.write(str(struct.x) + "," + str(struct.y) + "," + str(struct.level) + "/")
fmap.write("|")
for struct in headquarter:
fmap.write(str(struct.x) + "," + str(struct.y) + "," + str(struct.level - 1) + "/")
fmap.write("|")
for struct in resources:
fmap.write(str(struct.x) + "," + str(struct.y) + "/")
fmap.write("\n")
fmap.close()
structure = []
# Button to show the damage progress and stars earned
damageButton = Button(10, 10, 300, 130, (51, 51, 51), (51, 51, 51))
star1 = pygame.image.load("Images/1-stars.png")
size = star1.get_size()
star01 = pygame.transform.scale(star1, (size[0]/5, size[1]/5))
star2 = pygame.image.load("Images/2-stars.png")
size = star2.get_size()
star02 = pygame.transform.scale(star2, (size[0]/5, size[1]/5))
star3 = pygame.image.load("Images/3-stars.png")
size = star3.get_size()
star03 = pygame.transform.scale(star3, (size[0]/5, size[1]/5))
def damageDone(fraction, structs):
global victory, stars
hqThere = False
for struct in structs:
if struct.type == "HEADQUARTERS":
hqThere = True
break
percent = int(float(fraction)*100)
if percent == 100:
damageButton.addImage(star03, (damageButton.w/2, damageButton.h/2 - 30))
victory = True
stars = 3
elif not hqThere and percent >= 50:
damageButton.addImage(star02, (damageButton.w/2, damageButton.h/2 - 30))
victory = True
stars = 2
elif (percent >= 50) or (not hqThere and percent < 50):
damageButton.addImage(star01, (damageButton.w/2, damageButton.h/2 - 30))
victory = True
stars = 1
elif percent < 50 and hqThere:
damageButton.image = None
victory = False
stars = 0
damageButton.draw()
pygame.draw.rect(display, (208, 211, 212), (damageButton.x + 50, damageButton.y + damageButton.h - 50, 200, 30))
w = 2*percent
pygame.draw.rect(display, (142, 68, 173), (damageButton.x + 50 + 1, damageButton.y + damageButton.h - 50 + 1, w - 2, 30 - 2))
def drawBorder():
pygame.draw.rect(display, black, (margin, margin, groundW, groundH), 2)
def close():
pygame.quit()
sys.exit()
# Pause the Game
def pause():
font = pygame.font.SysFont("Showcard Gothic", 70)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
close()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_q:
close()
if event.key == pygame.K_ESCAPE:
return
if event.key == pygame.K_m:
global loop
loop = False
return
pauseText = font.render("PAUSED", True, (255, 255, 200))
resume = font.render("\'ESCAPE\' to RESUME", True, (140, 200, 50))
main = font.render("\'M\' to MAIN MENU", True, (200, 200, 255))
quit = font.render("\'Q\' to QUIT", True, (200, 255, 200))
display.blit(pauseText, (200, height/2 - 150))
display.blit(resume, (200, height/2 - 50))
display.blit(main, (200, height/2 + 50))
display.blit(quit, (200, height/2 + 150))
pygame.display.update()
clock.tick(60)
# Maps class
class Maps:
def __init__(self):
fmap = open("Data/maps", "r")
data = fmap.read().split("\n")
fmap .close()
data.pop(-1)
for i in range(len(data)):
data[i] = data[i].split("|")
for j in range(len(data[i])):
data[i][j] = data[i][j].split("/")
if len(data[i][j]) > 1:
data[i][j].pop(-1)
if not (data[i][j] == ['']):
for k in range(len(data[i][j])):
data[i][j][k] = [int(float(x)) for x in data[i][j][k].split(",")]
self.maps = data[:]
fp = open("Data/mapReached", "rb")
self.mapNum = int(float(fp.read()))
fp.close()
fmap = open("Data/customMaps", "r")
data = fmap.read().split("\n")
fmap.close()
data.pop(-1)
for i in range(len(data)):
data[i] = data[i].split("|")
for j in range(len(data[i])):
data[i][j] = data[i][j].split("/")
if len(data[i][j]) > 1:
data[i][j].pop(-1)
if not (data[i][j] == ['']):
for k in range(len(data[i][j])):
data[i][j][k] = [int(float(x)) for x in data[i][j][k].split(",")]
self.customMaps = data[:]
self.mode = "adventure"
self.font = pygame.font.SysFont("Agency FB", 100)
def createMap(self):
global presentLevel, loop
global structure, noCannon, noMortar, noTower , noHquart, noResource
loop = True
maxCannon = 4
maxMortar = 2
maxTower = 4
maxHquart = 1
maxResource = 10
noCannon = 0
noMortar = 0
noTower = 0
noHquart = 0
noResource = 0
canMaxLevel = 4
morMaxLevel = 3
towMaxLevel = 4
hqMaxLevel = 5
structure = []
level = []
for i in range(5):
h = 40
w = 40
x = 100*(i + 1) + w*i
y = margin + 20
newButton = Button(x, y, w, h, blue, (93, 173, 226), levelActive)
newButton.arg = i + 1
newButton.addText(str(i+1), (0, 0), 20)
level.append(newButton)
inventory = []
for i in range(5):
h = 100
x = width - 140
y = 10*(i + 1) + h*i
newButton = Button(x, y, 130, h, blue, (93, 173, 226), active)
inventory.append(newButton)
save = Button(width - 140, height - 70, 130, 50, blue, (93, 173, 226), saveMap)
save.addText("SAVE MAP", (0, 0), 20)
inventory[0].addText("CANNONS" + ": " + str(maxCannon), (0, 0), 20)
inventory[1].addText("MORTARS" + ": " + str(maxMortar), (0, 0), 20)
inventory[2].addText("TOWERS" + ": " + str(maxTower), (0, 0), 20)
inventory[3].addText("HEADQUARTERS" + ": " + str(maxHquart), (0, 0), 20)
inventory[4].addText("RESOURCE" + ": " + str(maxResource), (0, 0), 20)
inventory[0].arg = 1
inventory[1].arg = 2
inventory[2].arg = 3
inventory[3].arg = 4
inventory[4].arg = 5
while loop:
inventory[0].updateText("CANNONS" + ": " + str(maxCannon - noCannon), (0, 0))
inventory[1].updateText("MORTARS" + ": " + str(maxMortar - noMortar), (0, 0))
inventory[2].updateText("TOWERS" + ": " + str(maxTower - noTower), (0, 0))
inventory[3].updateText("H.Q." + ": " + str(maxHquart - noHquart), (0, 0))
inventory[4].updateText("RESOURCE" + ": " + str(maxResource - noResource), (0, 0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
close()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_q:
close()
if event.key == pygame.K_ESCAPE or event.key == pygame.K_SPACE or pygame.key == pygame.K_p:
pause()
if event.key == pygame.K_z and len(structure):
type = structure[len(structure) - 1].type
if type == "CANNON":
structure.pop(-1)
noCannon -= 1
elif type == "MORTAR":
structure.pop(-1)
noMortar -= 1
elif type == "TOWER":
structure.pop(-1)
noTower -= 1
elif type == "H.Q. ":
structure.pop(-1)
noHquart -= 1
elif type == "RESOURCE":
structure.pop(-1)
noResource -= 1
if event.type == pygame.MOUSEBUTTONDOWN:
inventory[0].select()
inventory[1].select()
inventory[2].select()
inventory[3].select()
inventory[4].select()
level[0].select()
level[1].select()
level[2].select()
level[3].select()
level[4].select()
save.arg = structure
save.select()
pos = pygame.mouse.get_pos()
if (margin < pos[0] < groundW + margin) and (margin < pos[1] < groundH + margin):
if (margin2 < pos[0] < validW + margin2) and (margin2 < pos[1] < validH + margin2):
if activeButton == 1 and noCannon < maxCannon:
if presentLevel > canMaxLevel:
presentLevel = canMaxLevel
newCannon = Cannon(pos[0], pos[1], canInfo["w"], canInfo["h"], canInfo["size"], canInfo["range"], canInfo["baseR"],
presentLevel, canInfo["shotR"], canInfo["shotSpeed"])
structure.append(newCannon)
noCannon += 1
if activeButton == 2 and noMortar < maxMortar:
if presentLevel > morMaxLevel:
presentLevel = morMaxLevel
newMortar = Mortar(pos[0], pos[1], mortarInfo["w"], mortarInfo["h"], mortarInfo["r"], mortarInfo["range"],
presentLevel, mortarInfo["shotR"],
mortarInfo["shotSpeed"])
structure.append(newMortar)
noMortar += 1
if activeButton == 3 and noTower < maxTower:
if presentLevel > towMaxLevel:
presentLevel = towMaxLevel
newTower = Tower(pos[0], pos[1], towerInfo["w"], towerInfo["h"], towerInfo["size"], towerInfo["range"],
towerInfo["baseR"], presentLevel, towerInfo["shotR"], towerInfo["shotSpeed"])
structure.append(newTower)
noTower += 1
if activeButton == 4 and noHquart < maxHquart:
if presentLevel > hqMaxLevel:
presentLevel = hqMaxLevel
newHQ = HeadQuarters(pos[0], pos[1], hqInfo["r"], presentLevel)
structure.append(newHQ)
noHquart += 1
if activeButton == 5 and noResource < maxResource:
newResource = Resource(pos[0], pos[1])
structure.append(newResource)
noResource += 1
display.fill((154,102,64))
pygame.draw.rect(display, (195,151,98), (margin, margin, groundW, groundH))
pygame.draw.rect(display, (154,102,64), (margin2, margin2, validW, validH))
drawBorder()
pygame.draw.rect(display, gray, (width - 150, 0, 150, height))
for struct in structure:
if struct.type == "HEADQUARTERS" or struct.type == "RESOURCE":
struct.draw()
else:
struct.draw([])
struct.shoot()
for item in inventory:
item.draw(activeButton)
if activeButton == 1:
for i in range(canMaxLevel):
level[i].draw(presentLevel)
elif activeButton == 2:
for i in range(morMaxLevel):
level[i].draw(presentLevel)
elif activeButton == 3:
for i in range(towMaxLevel):
level[i].draw(presentLevel)
elif activeButton == 4:
for i in range(hqMaxLevel):
level[i].draw(presentLevel)
save.draw()
pygame.display.update()
clock.tick(60)
def showResult(self):
def quitGame(event=0):
global loop
loop = False
if victory:
if self.mode == "adventure":
fp = open("Data/mapReached", "wb")
fp.write(str(self.mapNum + 1))
fp.close()
fp = open("Data/mapReached", "rb")
print(fp.read())
fp.close()
text = self.font.render("VICTORY", True, (255, 255, 255))
else:
text = self.font.render("LOSS", True, (255, 255, 255))
last = False
if self.mode == "adventure":
if victory and self.mapNum == len(self.maps) - 1:
endReached = self.font.render("All Bases Conquered!", True, (200, 200, 200))
pos2 = endReached.get_rect()
pos2.center = [width/2, 200]
last = True
if stars == 1:
pos = star1.get_rect()
pos.center = [width/2, height/2]
display.blit(star1, pos)
elif stars == 2:
pos = star2.get_rect()
pos.center = [width/2, height/2]
display.blit(star2, pos)
elif stars == 3:
pos = star3.get_rect()
pos.center = [width/2, height/2]
display.blit(star3, pos)
pos = text.get_rect()
pos.center = [width/2, height/2]
if victory:
next = Button(width/2 - 100 - 150, height/2 + 200, 200, 100, blue, blue, self.openMap)
if last:
next.addText("START AGAIN", (0, 0), 30)
else:
next.addText("NEXT MAP", (0, 0), 30)
next.arg = [1, self.mode]
else:
next = Button(width/2 - 100 - 150, height/2 + 200, 200, 100, blue, blue, self.openMap)
next.addText("ATTACK AGAIN", (0, 0), 30)
next.arg = [0, self.mode]
quit = Button(width/2 - 100 + 150, height/2 + 200, 200, 100, blue, blue, quitGame)
quit.addText("QUIT", (0, 0), 30)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
close()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_q:
close()
if event.type == pygame.MOUSEBUTTONDOWN:
next.select()
quit.select()
display.blit(text, pos)
if last:
display.blit(endReached, pos2)
next.draw()
quit.draw()
if not loop:
return
clock.tick(60)
pygame.display.update()
def openMap(self, arg):
global loop
self.mode = arg[1]
loop = True
global presentLevel
defenceStruct = []
if self.mode == "adventure":
self.mapNum = (self.mapNum + arg[0])%len(self.maps)
else:
self.mapNum = (self.mapNum + arg[0])%len(self.customMaps)
if self.mode == "adventure":
map = self.maps[self.mapNum]
else:
map = self.customMaps[self.mapNum]
cannonCoord = map[0]
mortarCoord = map[1]
towerCoord = map[2]
hqCoord = map[3]
resourceCoord = map[4]
if not (cannonCoord == [""]):
for pos in cannonCoord:
newCannon = Cannon(pos[0], pos[1], canInfo["w"], canInfo["h"], canInfo["size"],
canInfo["range"], canInfo["baseR"], pos[2],
canInfo["shotR"], canInfo["shotSpeed"])
defenceStruct.append(newCannon)
if not (mortarCoord == [""]):
for pos in mortarCoord:
newMortar = Mortar(pos[0], pos[1], mortarInfo["w"], mortarInfo["h"], mortarInfo["r"],
mortarInfo["range"], pos[2], mortarInfo["shotR"],
mortarInfo["shotSpeed"])
defenceStruct.append(newMortar)
if not (towerCoord == [""]):
for pos in towerCoord:
newTower = Tower(pos[0], pos[1], towerInfo["w"], towerInfo["h"], towerInfo["size"],
towerInfo["range"], towerInfo["baseR"], pos[2],
towerInfo["shotR"], towerInfo["shotSpeed"])
defenceStruct.append(newTower)
if not (hqCoord == [""]):
for pos in hqCoord:
newHQ = HeadQuarters(pos[0], pos[1], hqInfo["r"], pos[2])
defenceStruct.append(newHQ)
if not (resourceCoord == [""]):
for pos in resourceCoord:
newResource = Resource(pos[0], pos[1])
defenceStruct.append(newResource)
if self.mode == "custom":
level = []
for i in range(5):
h = 40
w = 40
x = width - 75 - 20
y = height/2 + (h + 10)*i
newButton = Button(x, y, w, h, blue, (93, 173, 226), levelActive)
newButton.arg = i + 1
newButton.addText(str(i+1), (0, 0), 20)
level.append(newButton)
troops = []
inventory = []
for i in range(3):
h = 100
x = width - 140
y = 10*(i + 1) + h*i
newButton = Button(x, y, 130, h, blue, (93, 173, 226), active)
inventory.append(newButton)
if self.mode == "custom":
maxShooter = 20
maxTank = 5
maxHeli = 3
shooterMaxLevel = 5
tankMaxLevel = 4
heliMaxLevel = 3
else:
if self.mapNum < 4:
maxShooter = 12
maxTank = 0
maxHeli = 0
shooterMaxLevel = 1
tankMaxLevel = 0
heliMaxLevel = 0
elif self.mapNum < 8:
maxShooter = 15
maxTank = 1
maxHeli = 0
shooterMaxLevel = 2
tankMaxLevel = 1
heliMaxLevel = 0
elif self.mapNum < 12:
maxShooter = 15
maxTank = 2
maxHeli = 1
shooterMaxLevel = 3
tankMaxLevel = 2
heliMaxLevel = 1
elif self.mapNum < 16:
maxShooter = 18
maxTank = 3
maxHeli = 2
shooterMaxLevel = 4
tankMaxLevel = 3
heliMaxLevel = 2
else:
maxShooter = 20
maxTank = 5
maxHeli = 3
shooterMaxLevel = 5
tankMaxLevel = 4
heliMaxLevel = 3
if self.mode == "custom":
next = Button(width - 130, height - 100, 100, 40, blue, blue, self.openMap)
next.addText("NEXT MAP", (0, 0), 20)
next.arg = [1, self.mode]
noShooter = 0
noTank = 0
noHeli = 0
inventory[0].addText("SHOOTER" + ": " + str(maxShooter), (0, 0), 20)
inventory[1].addText("TANK" + ": " + str(maxTank), (0, 0), 20)
inventory[2].addText("HELICOPTER" + ": " + str(maxHeli), (0, 0), 20)
inventory[0].arg = 1
inventory[1].arg = 2
inventory[2].arg = 3
initStruct = len(defenceStruct)
while loop:
inventory[0].updateText("SHOOTER" + ": " + str(maxShooter - noShooter), (0, 0))
inventory[1].updateText("TANK" + ": " + str(maxTank - noTank), (0, 0))
inventory[2].updateText("HELICOPTER" + ": " + str(maxHeli - noHeli), (0, 0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
close()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_q:
close()
if event.key == pygame.K_ESCAPE or event.key == pygame.K_SPACE or pygame.key == pygame.K_p:
pause()
if event.type == pygame.MOUSEBUTTONDOWN:
inventory[0].select()
inventory[1].select()
inventory[2].select()
if self.mode == "custom":
level[0].select()
level[1].select()
level[2].select()
level[3].select()
level[4].select()
next.select()
pos = pygame.mouse.get_pos()
if (margin < pos[0] < groundW + margin) and (margin < pos[1] < groundH + margin):
if not ((margin2 < pos[0] < margin2 + validW) and (margin2 < pos[1] < margin2 + validH)):
if activeButton == 1 and noShooter < maxShooter:
if self.mode == "custom":
if presentLevel > shooterMaxLevel:
presentLevel = shooterMaxLevel
newShooter = Shooter(pos[0], pos[1], 5, 1.2, 180, presentLevel, 5, 2)
else:
newShooter = Shooter(pos[0], pos[1], 5, 1.2, 180, shooterMaxLevel, 5, 2)
troops.insert(0, newShooter)
noShooter += 1
if activeButton == 2 and noTank < maxTank:
if self.mode == "custom":
if presentLevel > tankMaxLevel:
presentLevel = tankMaxLevel
newTank = Tank(pos[0], pos[1], 20, 1, 200, presentLevel, 6, 2)
else:
newTank = Tank(pos[0], pos[1], 20, 1, 200, tankMaxLevel, 6, 2)
troops.insert(0, newTank)
noTank += 1
if activeButton == 3 and noHeli < maxHeli:
if self.mode == "custom":
if presentLevel > heliMaxLevel:
presentLevel = heliMaxLevel
newHeli = Helicopter(pos[0], pos[1], 30, 0.7, 200, presentLevel, 7, 10)
else:
newHeli = Helicopter(pos[0], pos[1], 30, 0.7, 200, heliMaxLevel, 7, 10)
troops.append(newHeli)
noHeli += 1
display.fill((154,102,64))
pygame.draw.rect(display, (195,151,98), (margin, margin, groundW, groundH))
pygame.draw.rect(display, (154,102,64), (margin2, margin2, validW, validH))
drawBorder()
pygame.draw.rect(display, gray, (width - 150, 0, 150, height))
for item in inventory:
item.draw(activeButton)
for troop in troops:
troop.move(defenceStruct)
troop.draw()
troop.shoot()
troop.updateHealth(defenceStruct)
for struct in defenceStruct:
if not (struct.type == "HEADQUARTERS" or struct.type == "RESOURCE"):
struct.removeHit()
for struct in defenceStruct:
if struct.type == "HEADQUARTERS":
struct.draw()
elif struct.type == "RESOURCE":
struct.draw()
else:
struct.draw(troops)
struct.shoot()
struct.updateHealth(troops)
for troop in troops:
troop.removeHit()
for struct in defenceStruct:
if struct.health <= 0:
defenceStruct.remove(struct)
for troop in troops:
if troop.health <= 0:
troops.remove(troop)
if self.mode == "custom":
if activeButton == 1:
for i in range(shooterMaxLevel):
level[i].draw(presentLevel)
elif activeButton == 2:
for i in range(tankMaxLevel):
level[i].draw(presentLevel)
if activeButton == 3 :
for i in range(heliMaxLevel):
level[i].draw(presentLevel)
if self.mode == "custom" and noShooter == 0 and noTank == 0 and noHeli == 0:
next.draw()
damageDone(1.0 - float(len(defenceStruct))/initStruct, defenceStruct)
if (defenceStruct == []) or (noShooter == maxShooter and noTank == maxTank and noHeli == maxHeli and troops == []):
self.showResult()
pygame.display.update()
clock.tick(90)
if __name__ == "__main__":
width = 1260
height = 720
screen = pygame.display.set_mode((width, height))
initMaps(screen, (width, height), 25, 100)
newMap = Maps()
newMap.openMap([0, "adventure"])
#newMap.createMap()
close()