diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6c4f0e4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +__pycache__/ +*.py[cod] +test.py \ No newline at end of file diff --git a/Game.py b/Game.py deleted file mode 100644 index 7972d97..0000000 --- a/Game.py +++ /dev/null @@ -1,454 +0,0 @@ -#!/usr/bin/python3 - -import pygame as pg -import random -from math import sin, cos, tan, pi -import time - -pg.init() - -#COLORS -bgcolor = (204, 221, 255) -white = (255,255,255) -black = (0,0,0) -blue = (0,0,255) -red = (200,0,0) -light_red = (255,0,0) -yellow = (200,200,0) -light_yellow = (255,255,0) -green = (34,177,76) -light_green = (0,255,0) -wheelColor = (100,100,100) - -#Sounds -boom_sound = pg.mixer.Sound("Sounds/boom.wav") -gameover_sound = pg.mixer.Sound("Sounds/gameover.wav") -shot_sound = pg.mixer.Sound("Sounds/firecracker.wav") - -boom_image = pg.image.load("Photos/bang1.png") - -##pg.mixer.music.load("Sounds/ingame.it") -##pg.mixer.music.play(-1) - -#DISPLAY_WINDOW -dWidth = 800 -dHeight = 600 -block_size = 20 -dWidth = round(dWidth/block_size) *block_size -dHeight = round(dHeight/block_size)*block_size -screen = pg.display.set_mode((dWidth,dHeight)) -pg.display.set_caption('Tanks') - -#Game_data -groundHeight = 35 -gHeight = groundHeight -tankWidth = 40 -tankHeight = 20 -turretWidth = 3 -turretLength = 20 -wheelWidth = 4 -barrierWidth = 50 -maxPower = 100 -gravity = 6 -bombRadius = 4 - -#FONT_SIZES -smallFont = 25 -midFont = 45 -large = 75 - -#CLOCK -FPS = 15 -clock = pg.time.Clock() - -class Tank: - def __init__(self,player,angle,power = 50, machine = False,color = black): - self.pow = power - self.ang = angle - self.tankcolor = color - self.p = player - if player == -1: - self.tankX = dWidth * 0.1 - else: - self.tankX = dWidth * 0.9 - self.tankY = dHeight - (groundHeight+tankHeight+wheelWidth) - self.health = 100 - self.moveX = 0 - self.chgAng = 0 - self.chgPow = 0 - self.damage = 0 - self.auto = machine - - def change(self): - if self.auto != True: - self.tankX += self.moveX - self.ang += self.chgAng - self.pow += self.chgPow - - elif self.auto == True: - self.tankX += random.randint(-15,15) - - - self.health -= self.damage - self.damage = 0 - if self.pow > maxPower: - self.pow = maxPower - elif self.pow <= 0: - self.pow = 1 - - def draw_tank(self): - #Drawing Tank - self.turEnd = self.Ends() - x = int(self.tankX) - y= int(self.tankY) - pg.draw.circle(screen, self.tankcolor,(x,y), int(tankHeight/2)) - pg.draw.rect(screen, self.tankcolor, (x-tankWidth/2,y,tankWidth, tankHeight)) - pg.draw.line(screen, black, (x,y),self.turEnd,turretWidth) - - #Drawing Wheels of Tank - numberOfWheel = tankWidth/wheelWidth - startX = int(tankWidth/2) - int((numberOfWheel - int(numberOfWheel))/2) - int(wheelWidth/2) - for i in range(int(numberOfWheel)): - pg.draw.circle(screen,wheelColor,(x-startX,y+tankHeight+int(wheelWidth/2)),int(wheelWidth/2)) - startX -= wheelWidth - - def healthBar(self): - if self.health > maxPower*0.75: - color1 = green - elif self.health > maxPower*0.3: - color1 = yellow - else: - color1 = red - - if self.health > 0: - pg.draw.rect(screen,color1,(dWidth/2 + self.p*dWidth/4 -50,50,self.health,25)) - else: - pass - - def calculatePower(self,mX,angle,eX,g): - power = (((mX-eX)*(-g))/sin(2*angle))**(1/2) #Using formula for velocity in projectile motion - randomizer = random.randint(-10,10)/100 - - power = int(power + power * randomizer) - if power > maxPower: - return maxPower - elif power < 0: - return 0 - else: - return int(power) - - def fire(self, enemyX): - global gravity,bombRadius - xy = self.turEnd - pos = list(self.turEnd) - fire = True - g = gravity - bombR = bombRadius - x,y = 0,0 - damage = 0 - self.pow = self.calculatePower(self.tankX,self.ang,enemyX,g) if self.auto else self.pow - t = 0 - while fire: - for event in pg.event.get(): - if event.type == pg.QUIT: - close_game() - screen.fill(bgcolor) - pg.draw.circle(screen, red, (int(pos[0]),int(pos[1])),bombR) - draw_objects(p1,p2) - x = self.pow * cos(self.ang) * t - y = x * tan(self.ang) - g/(2*(self.pow*cos(self.ang))**2) * x**2 - t += 0.2 - pos[0] = xy[0] + x - pos[1] = xy[1] - y - if pos[1] >= dHeight-gHeight: - fire = False - pg.mixer.Sound.play(boom_sound) - hit_x = int(pos[0]*(dHeight-gHeight)/pos[1]) - hit_y = dHeight-gHeight - self.explosion(hit_x, hit_y) - if enemyX-35 < hit_x < enemyX+35: - damage = 25 - abs((hit_x - enemyX)/7) - - - check_x1 = pos[0] <= barX + barrierWidth - check_x2 = pos[0] >= barX - - check_y1 = pos[1] <= dHeight - check_y2 = pos[1] >= dHeight - barH - - if check_x1 and check_x2 and check_y1 and check_y2: - fire = False - pg.mixer.Sound.play(boom_sound) - hit_x = int(pos[0]) - hit_y = int(pos[1]) - self.explosion(hit_x, hit_y) - - - pg.display.update() - clock.tick(100) - return damage - - def explosion(self,x,y ): - #time.sleep(0.01) - width = 20 - height = 20 - for i in range(10): - boom = pg.transform.scale(boom_image,(width,height)) - boom_rect = boom.get_rect() - boom_rect.center = x, y - screen.blit(boom, boom_rect) - pg.display.update() - clock.tick(50) - width += 5 - height += 5 - - - def Ends(self): - return (self.tankX+turretLength * cos(self.ang),self.tankY - turretLength * sin(self.ang)) - - def show_power(self): - message_to_screen("Power: "+ str(self.pow)+"%",black,x_displace = self.p*dWidth/4, y_displace = -dHeight/2 +20, size = smallFont) - - -def choosePlayer(): - intro = True - while intro == True: - for event in pg.event.get(): - if event.type == pg.QUIT: - close_game() - - screen.fill(bgcolor) - message_to_screen("Choose player mode",green,y_displace = -150,size = large) - - button("Single Player",330,400,200,50, green, light_green, "single") - button("Two Player",330,500,200,50, yellow, light_yellow, "multi") - pg.display.update() - clock.tick(5) - -def gameIntro(): - intro = True - while intro == True: - for event in pg.event.get(): - if event.type == pg.QUIT: - close_game() - - screen.fill(bgcolor) - message_to_screen("Welcome to Tanks",green,y_displace = -100,size = large) - message_to_screen("The objective of the game is to shoot destroy",black,y_displace = -30) - message_to_screen("the enemy tank before they destroy you.",black,y_displace = 10) - - button("Play",150,500,100,50, green, light_green, "start") - button("Controls",350,500,100,50, yellow, light_yellow, "controls") - button("Quit",550,500,100,50, red, light_red, "quit") - - pg.display.update() - clock.tick(5) - -def game_controls(): - controls = True - while controls == True: - for event in pg.event.get(): - if event.type == pg.QUIT: - close_game() - - screen.fill(bgcolor) - message_to_screen("Controls",green,y_displace = -200,size = large) - message_to_screen("Player 1 Player 2",black,x = 350, y = 200) - message_to_screen("Fire: Spacebar Spacebar",black,x = 150, y = 250) - message_to_screen("Change Angle: W,S Up & Down arrows",black,x = 150, y = 300) - message_to_screen("Move Tank: A,D Left & Right arrows",black,x = 150, y = 350) - message_to_screen("Change Power: Q,E Alt & Ctrl",black,x = 150, y = 400) - - - button("Play",150,500,100,50, green, light_green, "start") - button("Back",0,0,100,50, yellow, light_yellow, "main") - button("Quit",550,500,100,50, green, light_yellow, "quit") - - pg.display.update() - clock.tick(5) - -def message_to_screen(msg,color, x_displace = 0,y_displace=0, size = smallFont,x = None ,y = None): - font = pg.font.SysFont('comicsansms', size) - screen_text = font.render(msg, True, color) - text_rect = screen_text.get_rect() - if x == None and y == None: - text_rect.center = (dWidth/2)+x_displace, (dHeight/2)+y_displace - else: - text_rect.topleft = x, y - screen.blit(screen_text, text_rect) - -def close_game(): - pg.quit() - import sys - sys.exit() - -def draw_barrier(xlocation, barrierHeight, barrierWidth): - pg.draw.rect(screen, black, [xlocation, dHeight-barrierHeight,barrierWidth,barrierHeight]) - -def text_to_button(msg, color, x, y, width, height, size = 25): - font = pg.font.SysFont('comicsansms', size) - screen_text = font.render(msg, True, color) - text_rect = screen_text.get_rect() - text_rect.center = (x+(width/2)), (y+(height/2)) - screen.blit(screen_text, text_rect) - -def button(text, x, y, width, height,inactive_color,active_color, action=None): - cur = pg.mouse.get_pos() - click = pg.mouse.get_pressed() - global multiplayer - if x < cur[0] < x+width and y < cur[1] < y+height: - pg.draw.rect(screen, active_color, (x,y,width,height)) - - if click[0] == 1 and action != None: - - if action == "start": - choosePlayer() - elif action == "quit": - close_game() - elif action == "controls": - game_controls() - elif action == "main": - gameIntro() - elif action == 'single': - multiplayer = False - gameLoop() - elif action == 'multi': - multiplayer = True - gameLoop() - else: - pg.draw.rect(screen, inactive_color, (x,y,width,height)) - text_to_button(text, black, x, y, width, height) - -def gameOver(winner, loser): - pg.mixer.Sound.play(gameover_sound) - over = True - while over == True: - for event in pg.event.get(): - if event.type == pg.QUIT: - close_game() - - screen.fill(bgcolor) - message_to_screen("%s wins"%winner,black,y_displace = -100,size = midFont) - message_to_screen("%s loses"%loser,black,y_displace = -30, size = midFont) - - button("Play Again",150,500,150,50, green, light_green, "start") - button("Home",350,500,100,50, yellow, light_yellow, "main") - button("Quit",550,500,100,50, green, light_yellow, "quit") - pg.display.update() - clock.tick(5) - -def draw_objects(x,y,displace_message = None): - x.draw_tank() - y.draw_tank() - x.show_power() - y.show_power() - x.healthBar() - y.healthBar() - draw_barrier(barX, barH, barrierWidth) - screen.fill(green, [0,dHeight-gHeight,dWidth,gHeight]) - if displace_message != None: - message_to_screen("Your Turn",black,x_displace = displace_message,size = smallFont) - -def gameLoop(): - global barX, barH, p1, p2 - - try: multiplayer - except NameError: multiplayer = False - - barX = (dWidth/2) + random.randint(-0.2*dWidth,0.2*dWidth) - barH = random.randrange(dHeight*0.1, dHeight*0.6) - p1 = Tank(-1, pi/4,color = (150,30,40)) - if not multiplayer: - p2 = Tank(1, 3*pi/4,machine = True) - else: - p2 = Tank(1, 3*pi/4) - turn = 1 - game = True - while game: - for event in pg.event.get(): - if event.type == pg.QUIT: - close_game() - if event.type == pg.KEYDOWN: - if turn == 1: - if event.key == pg.K_a: - p1.moveX = -5 - elif event.key == pg.K_d: - p1.moveX = 5 - elif event.key == pg.K_w: - p1.chgAng = 0.1 - elif event.key == pg.K_s: - p1.chgAng = -0.1 - elif event.key == pg.K_e: - p1.chgPow = 1 - elif event.key == pg.K_q: - p1.chgPow = -1 - elif event.key == pg.K_SPACE: - p2.damage = p1.fire(p2.tankX) - turn = 2 - - - elif turn == 2 and multiplayer == True: - if event.key == pg.K_LEFT: - p2.moveX = -5 - elif event.key == pg.K_RIGHT: - p2.moveX = 5 - elif event.key == pg.K_UP: - p2.chgAng = -0.1 - elif event.key == pg.K_DOWN: - p2.chgAng = 0.1 - elif event.key == 305: - p2.chgPow = 1 - elif event.key == 307: - p2.chgPow = -1 - elif event.key == pg.K_SPACE: - p1.damage = p2.fire(p1.tankX) - turn = 1 - if event.type == pg.KEYUP: - if event.key in (pg.K_UP, pg.K_DOWN): - p2.chgAng = 0 - elif event.key in (pg.K_w, pg.K_s): - p1.chgAng = 0 - elif event.key in (pg.K_a, pg.K_d): - p1.moveX = 0 - elif event.key in (pg.K_LEFT, pg.K_RIGHT): - p2.moveX = 0 - elif event.key in (pg.K_q, pg.K_e): - p1.chgPow = 0 - elif event.key in (305, 307): - p2.chgPow = 0 - - screen.fill(bgcolor) - - p1.change() - - if multiplayer == True: - p2.change() - - if p1.tankX + 20 > barX: p1.tankX -= 5 - if p1.tankX - 20 < 0: p1.tankX += 5 - - if p2.tankX - 20 < barX + barrierWidth: p2.tankX += 5 - if p2.tankX + 20 > dWidth: p2.tankX -=5 - - if turn == 1: - x_displace = -dWidth/3 - elif turn == 2: - x_displace = dWidth/3 - - draw_objects(p1,p2,x_displace) - pg.display.update() - clock.tick(FPS) - - if multiplayer == False and turn == 2: - time.sleep(3) - p2.change() - p1.damage = p2.fire(p1.tankX) - turn = 1 - - if p2.health <= 0: gameOver("Player 1","Player 2") - if p1.health <= 0: gameOver("Player 2","Player 1") - - -gameIntro() -#gameLoop() - diff --git a/README.md b/README.md index 4637d02..fe8e9bf 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ cd Tanks - when you have cloned the repo, simply run the .py file in terminal ``` -python3 Game.py +python3 main.py ``` ---------- diff --git a/defs.py b/defs.py new file mode 100644 index 0000000..2248366 --- /dev/null +++ b/defs.py @@ -0,0 +1,65 @@ +import pygame as pg +from pygame.locals import * +pg.init() + +#COLORS +bgcolor = (204, 221, 255) +white = (255,255,255) +gray = (100,100,100) +black = (0,0,0) +blue = (0,0,255) +red = (200,0,0) +light_red = (255,0,0) +yellow = (200,200,0) +light_yellow = (255,255,0) +green = (34,177,76) +light_green = (0,255,0) +wheelColor = (100,100,100) + +#DISPLAY_WINDOW +dWidth = 800 +dHeight = 600 +##dWidth,dHeight = pg.display.Info().current_w,pg.display.Info().current_h +##block_size = 20 +##dWidth = round(dWidth/block_size) *block_size +##dHeight = round(dHeight/block_size)*block_size + + +##screen = pg.display.set_mode((0,0),FULLSCREEN) +screen = pg.display.set_mode((dWidth,dHeight)) +#pg.display.set_caption('Tanks') + +#Sounds +boom_sound = pg.mixer.Sound("Sounds/boom.wav") +gameover_sound = pg.mixer.Sound("Sounds/gameover.wav") +shot_sound = pg.mixer.Sound("Sounds/firecracker.wav") + +introbg = pg.image.load("tank.jpg") +introbg = pg.transform.scale(introbg, (dWidth,dHeight)) +boom_image = pg.image.load("Photos/bang1.png") + +##pg.mixer.music.load("Sounds/ingame.it") +##pg.mixer.music.play(-1) + +clock = pg.time.Clock() + +#Game_data +groundHeight = 35 +gHeight = groundHeight +tankWidth = 40 +tankHeight = 20 +turretWidth = 3 +turretLength = 25 +wheelWidth = 4 +barrierWidth = 50 +maxPower = 100 +gravity = 6 +bombRadius = 4 + +#FONT_SIZES +smallFont = 25 +midFont = 45 +large = 75 + +#CLOCK +FPS = 15 diff --git a/main.py b/main.py new file mode 100644 index 0000000..d3489b2 --- /dev/null +++ b/main.py @@ -0,0 +1,482 @@ +import pygame as pg +from defs import * +from sprites import * +from math import * +import random +import time +from textbox import * +from radiobutton import Radio + +players = [] +playersinfo = [] +totalplayers = 3 +objects = [] +wind = 0 +clock = pg.time.Clock() +time = 0 +colors = ['red','blue','green','pink','yellow','gray','orange'] + +def check_events(): + for event in pg.event.get(): + if event.type == pg.QUIT: + close_game() + elif event.type == pg.KEYDOWN: + if event.key == pg.K_ESCAPE: + close_game() + +def gameIntro(): + intro = True + while intro == True: + check_events() + + screen.fill(bgcolor) + screen.blit(introbg,introbg.get_rect()) + message_to_screen("Welcome to Tanks",black,y_displace = -180,size = large) + message_to_screen("The objective of the game is to shoot destroy",black,y_displace = -100) + message_to_screen("the enemy tank before they destroy you.",black,y_displace =-60) + + x = dWidth/2 + y = dHeight - 100 + play = button("Play",x-200,y,100,50, green, light_green, "chooseplayer") + control = button("Controls",x,y,100,50, yellow, light_yellow, "controls") + close = button("Quit",x+200,y,100,50, red, light_red, "quit") + + for response in (play,control,close): + if response != None: + return response + + pg.display.update() + clock.tick(5) + + +def choosePlayer(): + global resp + intro = True + resp = '' + + def setplayerinf(ids,number): + global totalplayers,resp,playersinfo + try: + if 1 < int(number) < 8: + totalplayers = int(number) + + for i in range(totalplayers): + data = {'name':'Tank'+str(i+1),'color':pg.Color('gray'),'human':True} + playersinfo.append(data) + resp = 'prop' + except: + pass + + inputbox = TextBox((dWidth/2-150,dHeight/2-30,300,70),command = setplayerinf) + + while intro == True: + for event in pg.event.get(): + if event.type == pg.QUIT: + close_game() + inputbox.get_event(event) + + screen.fill(bgcolor) + message_to_screen("Choose no of player",green,y_displace = -150,size = large) + + + inputbox.update() + inputbox.draw(screen) + + if resp == 'prop': + return resp + + pg.display.update() + clock.tick(5) + +def playerproperties(): + global pos,resp + controls = True + pos = 0 + resp = '' + color_buttons = [] + def setplayername(ids,name): + global pos,resp + playersinfo[pos]['name'] = name + + if pos == totalplayers-1: + resp = "main" + pos += 1 + + def setplayercolor(color): + playersinfo[pos]['color']=color + + + x = int(dWidth/2-60) + y = int(dHeight/2-60) + for color in colors: + rad = Radio(x,y,color_buttons,main_color=pg.Color(color),command = setplayercolor,active = color=='gray') + color_buttons.append(rad) + x += 50 + + inputbox = TextBox((dWidth/2-150,dHeight/2-30,300,60),command = setplayername) + while controls == True: + for event in pg.event.get(): + if event.type == pg.QUIT: + close_game() + inputbox.get_event(event) + for butt in color_buttons: + butt.get_event(event) + + screen.fill(bgcolor) + message_to_screen("Player:-"+str(pos+1),black,x_displace=-70,y_displace=-140,size=midFont) + message_to_screen("Name:- ",black,x_displace=-120,y_displace=-60) + if resp == 'main': + return resp + inputbox.update() + inputbox.draw(screen) + for butt in color_buttons: + butt.draw(screen) + + +## x = dWidth/2 +## y = dHeight/2 +## close = button("Quit",x+200,y,100,50, red, light_red, "quit") + + + pg.display.update() + clock.tick(5) + +def game_controls(): + controls = True + while controls == True: + check_events() + + screen.fill(bgcolor) + message_to_screen("Controls",green,y_displace = -200,size = large) + message_to_screen("Player 1 Player 2",black,x = 350, y = 200) + message_to_screen("Fire: Spacebar Spacebar",black,x = 150, y = 250) + message_to_screen("Change Angle: W,S Up & Down arrows",black,x = 150, y = 300) + message_to_screen("Move Tank: A,D Left & Right arrows",black,x = 150, y = 350) + message_to_screen("Change Power: Q,E Alt & Ctrl",black,x = 150, y = 400) + + + play = button("Play",150,500,100,50, green, light_green, "main") + intro = button("Back",0,0,100,50, yellow, light_yellow, "intro") + close = button("Quit",550,500,100,50, green, light_yellow, "quit") + + for response in (play,intro,close): + if response != None: + return response + + pg.display.update() + clock.tick(5) + +def gameOver(): + + try: + winner = players[0].name + except: + winner = 'Noone' + + pg.mixer.Sound.play(gameover_sound) + over = True + while over == True: + check_events() + + screen.fill(bgcolor) + message_to_screen("%s wins"%winner,black,size = midFont) + + x = int(dWidth/2) + play = button("Play Again",x-200,500,150,50, green, light_green, "main") + intro = button("Home",x,500,100,50, yellow, light_yellow, "intro") + close = button("Quit",x+200,500,100,50, green, light_yellow, "quit") + + for response in (play,intro,close): + if response != None: + return response + + pg.display.update() + clock.tick(5) + +def text_to_button(msg, color, x, y, width, height, size = 25): + font = pg.font.SysFont('comicsansms', size) + screen_text = font.render(msg, True, color) + text_rect = screen_text.get_rect() + text_rect.center = (x+(width/2)), (y+(height/2)) + screen.blit(screen_text, text_rect) + +def close_game(): + pg.quit() + import sys + sys.exit() + return None + +def message_to_screen(msg,color, x_displace = 0,y_displace=0, size = smallFont,x = None ,y = None): + font = pg.font.SysFont('comicsansms', size) + screen_text = font.render(msg, True, color) + text_rect = screen_text.get_rect() + if x == None and y == None: + text_rect.center = (dWidth/2)+x_displace, (dHeight/2)+y_displace + else: + text_rect.topleft = x, y + screen.blit(screen_text, text_rect) + +def button(text, x, y, width, height,inactive_color,active_color, action=None): + x = x - width/2 + y = y - width/2 + cur = pg.mouse.get_pos() + click = pg.mouse.get_pressed() + global multiplayer + if x < cur[0] < x+width and y < cur[1] < y+height: + pg.draw.rect(screen, active_color, (x,y,width,height)) + + if click[0] == 1 and action != None: + return action + else: + pg.draw.rect(screen, inactive_color, (x,y,width,height)) + + text_to_button(text, black, x, y, width, height) + return None + +def set_wind(): + global wind,time + if time > 100: + wind += random.randint(-2,2) + time = 0 + else: + time += 1 + return wind +def draw_objects(player): + for tanker in players: + tanker.draw_tank() + + for obj in objects: + obj.draw() + + w = set_wind() + show_power(player.power) + healthbar(player.gethealth()) + show_name(player.name) + show_score() + message_to_screen('Wind:- '+str(w),black,x = dWidth/2,y=5,size = smallFont) + +def healthbar(datas): + health = datas[0] + primary = datas[1] + secondary = datas[2] + pg.draw.rect(screen,secondary,(dWidth/2 - dWidth/4-50,50,maxPower,25)) + pg.draw.rect(screen,primary,(dWidth/2 - dWidth/4 -50,50,health,25)) + +def show_name(name): + message_to_screen('Turn:',black,x = 5,y = 5 ,size = smallFont) + message_to_screen( name ,blue,x = 5,y = 30,size = smallFont) + +def show_power(power): + message_to_screen("Power: "+ str(power)+"%",black,x_displace = -dWidth/4, y_displace = -dHeight/2 +20, size = smallFont) + +def fire(player): + xy = player.turEnd + pos = list(player.turEnd) + fire = True + g = gravity + bombR = bombRadius + x,y = 0,0 + damage = 0 + + + if player.human == False: + time.sleep(1) + player.calculateAngle(players) + player.calculatePower(players,randomize = False) + + power = player.power + t = 0 + while fire: + check_events() + screen.fill(bgcolor) + weapon = Missile(bombR,20,color=blue) + weapon.draw(int(pos[0]),int(pos[1])) + draw_objects(player) + + x = power * cos(player.ang) * t + wind*t/2 #Using formula from projectile motion + y = power * sin(player.ang) * t - (g*(t**2))/2 + + t += 0.2 + pos[0] = xy[0] + x + pos[1] = xy[1] - y + + for obj in players+objects: + if collided(weapon,obj): + weapon.explode() + fire = False + break + + if weapon.rect.left <=0 or weapon.rect.right >= dWidth: + fire = False + + pg.display.update() + clock.tick(100) + score = 0 + for tank in players: + score += setdamage(weapon.rect.center,tank)*100 + + for obj in objects[:-1]: + setdamage(weapon.rect.center,tank) + player.score += score + +def collided(sprite,target): + collide = False + if sprite != target: + if sprite.rect.colliderect(target.rect): + collide = True + + return collide + +def setdamage(center,target): + center2 = target.rect.center + damage = 55 - ((center[0] - center2[0])**2 + (center[1] - center2[1])**2)**(1/2) * 0.5 + if damage < 0: + damage = 0 + + target.health -= damage + return damage + +def validatemotion(player): + movable = True + pos = player.rect + move = player.moveX + + if pos.left<= 0 or pos.right >= dWidth: + movable = False + + for obj in players+objects[:-1]: + if collided(player,obj): + movable = False + + if not movable: + player.midX -= player.moveX + +def show_score(): + x = dWidth-200 + y = 40 + for player in players: + message_to_screen(player.name+':- '+str(int(player.score)),black,size=30,x=x,y=y) + y += 50 + +def makeBarrier(color): + bar = Barrier(color=color) + bar.draw() + for player in players+objects: + if collided(bar,player): + bar = makeBarrier(color) + return bar + +def gameLoop(): + global totalplayers + + try: multiplayer + except NameError: multiplayer = False + + x = tankWidth/2 + interval = (dWidth-tankWidth)/(totalplayers-1) + for tanker,tanker in zip(range(totalplayers),playersinfo): + player = Tank(tanker['name'],x,color = tanker['color'],human = tanker['human']) + players.append(player) + x += interval + + bar1 = makeBarrier(green) + objects.append(bar1) + bar2 = makeBarrier(blue) + objects.append(bar2) + + terrain = Terrain(gray,groundHeight) + + objects.append(terrain) + turn = 0 + draw_objects(players[turn]) + game = True + while game: + + if players[turn].human == False: + time.sleep(1) + fire(players[turn]) + turn = turn + 1 if turn < totalplayers -1 else 0 + + for event in pg.event.get(): + if event.type == pg.QUIT : + close_game() + if event.type == pg.KEYDOWN: + if event.key == pg.K_ESCAPE: + close_game() + elif event.key == pg.K_a : + players[turn].moveX = -5 + elif event.key == pg.K_d: + players[turn].moveX = 5 + elif event.key == pg.K_w: + players[turn].chgAng = 0.05 + elif event.key == pg.K_s: + players[turn].chgAng = -0.05 + elif event.key == pg.K_e: + players[turn].chgPow = 1 + elif event.key == pg.K_q: + players[turn].chgPow = -1 + elif event.key == pg.K_SPACE: + fire(players[turn]) + turn = turn + 1 if turn < totalplayers-1 else 0 + + + if event.type == pg.KEYUP: + if event.key in (pg.K_UP, pg.K_DOWN,pg.K_w, pg.K_s): + players[turn].chgAng = 0 + elif event.key in (pg.K_LEFT, pg.K_RIGHT,pg.K_a, pg.K_d): + players[turn].moveX = 0 + elif event.key in (pg.K_q, pg.K_e): + players[turn].chgPow = 0 + + + screen.fill(bgcolor) + + players[turn].change_values() + + for obj in players+objects[:-1]: + if obj.health <= 0: + if obj in players: + i = players.index(obj) + players.remove(obj) + totalplayers -= 1 + else: + objects.remove(obj) + + if i < turn: + turn -= 1 + elif i >= turn: + if turn+1 > totalplayers:turn=0 + + + draw_objects(players[turn]) + + pg.display.update() + validatemotion(players[turn]) + clock.tick(FPS) + + if len(players) == 1: + return 'over' + + + + + + + +##Main Program + +currScreen = gameIntro + +screens = {'intro':gameIntro,'controls':game_controls,'chooseplayer':choosePlayer, + 'main':gameLoop,'quit':close_game,'over':gameOver,'prop':playerproperties} +gameOn = True +while gameOn: + resp = currScreen() + if resp != None: + currScreen = screens[resp] + else: + gameOn = False + +gameLoop() +##choosePlayer() +##playerproperties() diff --git a/radiobutton.py b/radiobutton.py new file mode 100644 index 0000000..187ee86 --- /dev/null +++ b/radiobutton.py @@ -0,0 +1,54 @@ +import pygame as pg + + +class Radio: + def __init__(self,x,y,group = None,**kwargs): + self.group = group + self.center = (x,y) + self.process_kwargs(kwargs) + + def process_kwargs(self,kwargs): + defaults = {"id" : None, + "command" : None, + "active" : True, + "outer_radius":10, + "inner_radius":7, + "main_color" : pg.Color("green"), + "selected_color":pg.Color("black"), + "outline_color" : pg.Color("black"), + "outline_width" : 2, + "active_color" : pg.Color("blue")} + + for kwarg in kwargs: + if kwarg in defaults: + defaults[kwarg] = kwargs[kwarg] + else: + raise KeyError("InputBox accepts no keyword {}.".format(kwarg)) + + self.__dict__.update(defaults) + + def get_event(self,event): + if event.type == pg.MOUSEBUTTONDOWN and event.button == 1: + x,y = event.pos + h,k = self.center + r = self.outer_radius + if (x-h)**2 + (y-k)**2 <= r**2: + self.execute() + + def execute(self): + if self.group: + for butt in self.group: + butt.active = False + self.active = True + + if self.command: + self.command(self.main_color) + + def draw(self,surface): + #print(self.outline_color,self.main_color,self.center,int(self.outer_radius+self.outline_width)) + pg.draw.circle(surface,self.outline_color,self.center,int(self.outer_radius+self.outline_width)) + pg.draw.circle(surface,self.main_color,self.center,self.outer_radius) + if self.active: + pg.draw.circle(surface,self.selected_color,self.center,self.inner_radius) + + diff --git a/sprites.py b/sprites.py new file mode 100644 index 0000000..f19ad5b --- /dev/null +++ b/sprites.py @@ -0,0 +1,188 @@ +import pygame as pg +from defs import * +import random +from math import * + +class Object: + def __init__(self): + self.screen = screen + +class Tank(Object): + def __init__(self,name,posX,human = True,color = (0,0,0)): + Object.__init__(self) + self.name = name + self.power = 50 + self.score = 0 + self.ang = pi/4 + self.color = color + self.midX = posX + self.midY = dHeight - (groundHeight+tankHeight+wheelWidth) + self.health = 100 + self.moveX = 0 + self.chgAng = 0 + self.chgPow = 0 + self.damage = 0 + self.human = human + self.movable = True + self.draw_tank() + + def change_values(self): + + if self.human == True: + + self.lastmove = self.moveX + self.ang += self.chgAng + self.power += self.chgPow + + elif self.human == False: + self.midX += random.randint(-15,15) + + if self.movable: + self.midX += self.moveX + else: + self.moveX = 0 + + + self.health -= self.damage + self.damage = 0 + if self.power > maxPower: + self.power = maxPower + elif self.power <= 0: + self.power = 1 + + def draw_tank(self): + #Drawing Tank + self.turEnd = self.Ends() + x = int(self.midX) + y= int(self.midY) + pg.draw.circle(self.screen, self.color,(x,y), int(tankHeight/2)) + self.rect = pg.draw.rect(self.screen, self.color, (x-tankWidth/2,y,tankWidth, tankHeight)) + pg.draw.line(self.screen, black, (x,y),self.turEnd,turretWidth) + + #Drawing Wheels of Tank + numberOfWheel = tankWidth/wheelWidth + startX = int(tankWidth/2) - int((numberOfWheel - int(numberOfWheel))/2) - int(wheelWidth/2) + for i in range(int(numberOfWheel)): + pg.draw.circle(self.screen,wheelColor,(x-startX,y+tankHeight+int(wheelWidth/2)),int(wheelWidth/2)) + startX -= wheelWidth + + def gethealth(self): + bgcolor = gray + if self.health > maxPower*0.75: + color = green + elif self.health > maxPower*0.3: + color = yellow + else: + color = red + + return self.health,color,bgcolor + +## if self.health > 0: +## pg.draw.rect(self.screen,color1,(dWidth/2 + -1*dWidth/4 -50,50,self.health,25)) +## else: +## pass + + + def nearestEnemy(self,players): + nearest = None + eX = dWidth + for player in players: + if player == self: + continue + newex = abs(player.rect.centerx - self.midX) + if newex < eX: + nearest = player + ex = newex + return nearest + + def calculatePower(self,players,randomize = True): + mX = self.midX + angle = self.ang + g = gravity + + nearest = self.nearestEnemy(players) + if nearest == None:return + eX = nearest.midX + Hrange = abs(mX-eX) + power = abs((-Hrange*g)/sin(2*angle))**(1/2) #Using formula for velocity in projectile motion + if randomize: + randomizer = random.randint(-10,10)/100 + else: + randomizer = 0 + power = int(power + power * randomizer) + if power > maxPower: + self.power = maxPower + elif power < 0: + #print(power) + self.power = int(abs(power)) + else: + self.power = int(power) + + def calculateAngle(self,players): + angle = pi/4 + nearest = self.nearestEnemy(players) + if nearest == None:return + if nearest.midX < self.midX: + angle = 3*pi/4 + + self.ang = angle + + + def Ends(self): + return (self.midX+turretLength * cos(self.ang),self.midY - turretLength * sin(self.ang)) + + +class Barrier(Object): + def __init__(self,color = black): + Object.__init__(self) + self.screen = screen + self.color = color + self.barWidth = barrierWidth + self.barX = (dWidth/2) + random.randint(int(-0.2*dWidth),int(0.2*dWidth)) + self.barH = random.randrange(int(dHeight*0.3), int(dHeight*0.7)) + self.barHeight = self.barH + self.damage = 0 + self.health = 200 + + def draw(self): + self.rect = pg.draw.rect(self.screen, self.color, [self.barX, dHeight-self.barHeight,self.barWidth,self.barHeight]) + + +class Terrain(Object): + def __init__(self,color,height,strength = 0): + Object.__init__(self) + self.color = color + self.height = height + self.strength = strength + self.damage = 0 + + def draw(self): + self.rect = pg.draw.rect(self.screen,self.color,[0,dHeight-self.height,dWidth,dHeight]) + +class Missile(Object): + def __init__(self,radius,damage,color = red): + Object.__init__(self) + self.radius = radius + self.damage = damage + self.color = color + self.screen = screen + + def draw(self,X,Y): + self.rect = pg.draw.circle(self.screen,self.color,(X,Y),self.radius) + + def explode(self): + boom_sound.set_volume(0.1) + pg.mixer.Sound.play(boom_sound) + #time.sleep(0.01) + width = 20 + height = 20 + x,y = self.rect.center + for i in range(10): + boom = pg.transform.scale(boom_image,(width,height)) + boom_rect = boom.get_rect() + boom_rect.center = x, y + self.screen.blit(boom, boom_rect) + pg.display.update() + clock.tick(50) + width += 5 + height += 5 diff --git a/tank.jpg b/tank.jpg new file mode 100644 index 0000000..61d44a6 Binary files /dev/null and b/tank.jpg differ diff --git a/textbox.py b/textbox.py new file mode 100644 index 0000000..20a769d --- /dev/null +++ b/textbox.py @@ -0,0 +1,86 @@ +import string +import pygame as pg + + +ACCEPTED = string.ascii_letters+string.digits+string.punctuation+" " + + +class TextBox(object): + def __init__(self,rect,**kwargs): + self.rect = pg.Rect(rect) + self.buffer = [] + self.final = None + self.rendered = None + self.render_rect = None + self.render_area = None + self.blink = True + self.blink_timer = 0.0 + self.process_kwargs(kwargs) + + def process_kwargs(self,kwargs): + defaults = {"id" : None, + "command" : None, + "active" : True, + "color" : pg.Color("white"), + "font_color" : pg.Color("black"), + "outline_color" : pg.Color("black"), + "outline_width" : 2, + "active_color" : pg.Color("blue"), + "font" : pg.font.Font(None, 50), + "clear_on_enter" : True, + "inactive_on_enter" : False} + for kwarg in kwargs: + if kwarg in defaults: + defaults[kwarg] = kwargs[kwarg] + else: + raise KeyError("InputBox accepts no keyword {}.".format(kwarg)) + self.__dict__.update(defaults) + + def get_event(self,event): + if event.type == pg.KEYDOWN and self.active: + if event.key in (pg.K_RETURN,pg.K_KP_ENTER): + self.execute() + elif event.key == pg.K_BACKSPACE: + if self.buffer: + self.buffer.pop() + elif event.unicode in ACCEPTED: + self.buffer.append(event.unicode) + elif event.type == pg.MOUSEBUTTONDOWN and event.button == 1: + pass + #self.active = self.rect.collidepoint(event.pos) + + def execute(self): + if self.command: + self.command(self.id,self.final) + self.active = not self.inactive_on_enter + if self.clear_on_enter: + self.buffer = [] + + def update(self): + new = "".join(self.buffer) + if new != self.final: + self.final = new + self.rendered = self.font.render(self.final, True, self.font_color) + self.render_rect = self.rendered.get_rect(x=self.rect.x+2, + centery=self.rect.centery) + if self.render_rect.width > self.rect.width-6: + offset = self.render_rect.width-(self.rect.width-6) + self.render_area = pg.Rect(offset,0,self.rect.width-6, + self.render_rect.height) + else: + self.render_area = self.rendered.get_rect(topleft=(0,0)) + if pg.time.get_ticks()-self.blink_timer > 200: + self.blink = not self.blink + self.blink_timer = pg.time.get_ticks() + + def draw(self,surface): + outline_color = self.active_color if self.active else self.outline_color + outline = self.rect.inflate(self.outline_width*2,self.outline_width*2) + surface.fill(outline_color,outline) + surface.fill(self.color,self.rect) + if self.rendered: + surface.blit(self.rendered,self.render_rect,self.render_area) + if self.blink and self.active: + curse = self.render_area.copy() + curse.topleft = self.render_rect.topleft + surface.fill(self.font_color,(curse.right+1,curse.y,2,curse.h))