Build Your Own Tank Game in Python with Source Code Provided!

02 May 2023 Balmiki Mandal 0 Python

Creating a Tank Game with Python and Source Code

Have you ever wanted to create your own tank game using Python? With this step-by-step guide, you can easily create a tank game in Python with source code. This tutorial will show you how to create a basic tank game in Python with the help of Pygame. This tutorial will also provide you with open source code so that you can continue to customize and edit your tank game as much as you’d like.

What You'll Need

  • Python 3.x
  • Pygame
  • A Text Editor (optional)

Creating the Game

To get started, you will first need to set up your game window. This will be the canvas for your game. To do this, you will need to open a new Python file in your text editor. We will call this file ‘tankgame.py’. Once you have opened the file, you need to import all of the necessary modules required for the game.

Required pygame module.

import pygame, sys

import pygame.locals

Once your modules are imported, you will need to initialise pygame. You can do this by using the init() function.

pygame.init()

The next step is to create the game window. This will act as your canvas for the game. You can create the game window by using the set_mode() function. You can specify the size of the window by passing two parameters into the function. The first parameter is the width and the second is the height.

screen = pygame.display.set_mode((800,600))

Once your window is created, you will need to add some colors to your game. You can do this by using the color() function. You can add as many colors as you like to your game. For this example, we will use three colors; black, white and red.

BLACK = (0,0,0)
WHITE = (255,255,255)
RED = (255,0,0)

Now that we have all of our colors set, we will move on to setting up the game loop. The game loop will be responsible for running the game until it is quit. We can set this up by using the while loop.

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit();
            sys.exit();

Now that we have our game loop set, we are ready to add the tanks to the game. We can do this by using the draw.circle() function. We will need to create two tanks; one for our player and one for the computer. We can pass in some parameters to this function to customize our tanks.

playerTank = pygame.draw.circle(screen, RED, (400, 300), 15)
computerTank = pygame.draw.circle(screen, WHITE, (400, 300), 15)

Now that we have our tanks, we can add movement to them. We can do this by using the pygame.key.get_pressed() function. This will allow us to detect when the user is pressing a key on the keyboard. We can then use an if statement to check which key is being pressed and update the position of the tank accordingly. For this example, we will use the left, right, down and up arrow keys.

if event.type == pygame.KEYDOWN: 
    if event.key == pygame.K_LEFT:
        playerTank.x -= 10 
    elif event.key == pygame.K_RIGHT:
        playerTank.x += 10 
    elif event.key == pygame.K_UP:
        playerTank.y -= 10 
    elif event.key == pygame.K_DOWN:
        playerTank.y += 10

Now that our tanks can move, we can add collision detection to the game. We can use the colliderect() function to check whether the player’s tank has collided with the computer’s tank. If there is a collision, the game will end.

if playerTank.colliderect(computerTank):
    pygame.quit()
    sys.exit()

We also need to add some scoring to the game. We can use the pygame.font.SysFont() function to create a font for our game. Then we can use the draw.text() function to draw the text on the screen.

font = pygame.font.SysFont("comicsansms", 20)
text = font.render("Score: " + str(score), True, WHITE)
screen.blit(text,(50,50))

The last step is to add sound to the game. We can do this by using the pygame.mixer.Sound() function. We can then load the sound file into the game and play it using the play() function.

sound = pygame.mixer.Sound("explosion.wav")
sound.play()

Now that we have all of our game components, we need to tie everything together. We can do this by closing the while loop and adding the update() and flip() functions. These two functions will refresh the game window and update any changes that have been made. We also need to add a pygame.quit() and sys.exit() at the end of our game to ensure that the game window closes when the game is over.

while True:
    #All of the game code
    
pygame.display.update()
pygame.display.flip()

pygame.quit()
sys.exit()

That’s it! Your tank game is now ready to be played. Congratulations! You now know how to create a tank game with Python. Feel free to edit and customize your game as much as you’d like. Good luck and happy coding!

Full source code

#Importing Python modules
import pygame
import time
import random

#Initiating pygame and global variables
pygame.init()

width = 800
height = 600

gameWin = pygame.display.set_mode((width, height))
pygame.display.set_caption('DataFlair Tanks Game')
clock = pygame.time.Clock()

tankWidth = 40
tankHeight = 20
turretWidth = 5
wheelWidth = 5
groundHeight = 35

#Creating function for tank
def tank(x, y, turPos,tank):
    #tank=1 if player's tank and -1 if computer's tank
    x = int(x)
    y = int(y)
    locs=[[27,2],[26,5],[25,8],[23,12],[20,14],[18,15],[15,17],[13,19],[11,21]]
    possibleTurrets=[]
    for i in locs:
        possibleTurrets.append((x-tank*i[0],y-i[1]))

    pygame.draw.circle(gameWin, '#000000', (x, y), int(tankHeight / 2))
    
    for i in range(-15,16,5):
        pygame.draw.circle(gameWin,'#000000', (x+i, y + 20), wheelWidth)

    return possibleTurrets[turPos]


#Function to show text on screen
def textObjects(text, color, size="small"):
    if size == "vsmall":
        font=pygame.font.SysFont("Calibre", 15)
        textSurf = font.render(text, True, color)
    if size == "small":
        font=pygame.font.SysFont("Calibre", 25)
        textSurf = font.render(text, True, color)
    if size == "medium":
        font=pygame.font.SysFont("Calibre", 35)
        textSurf = font.render(text, True, color)
    if size == "large":
        font=pygame.font.SysFont("Calibre", 50)
        textSurf = font.render(text, True, color)
    return textSurf, textSurf.get_rect()

def show_message(msg, color, y_displace=0, size="small"):
    textSurf, textRect = textObjects(msg, color, size)
    textRect.center = (int(width / 2), int(height / 2) + y_displace)
    gameWin.blit(textSurf, textRect)

#Creating button class
class Button:
    """Create a button, then blit the surface in the while loop"""
 
    def __init__(self, text,pos, font, bg="blue"):
        self.x, self.y = pos
        self.font = pygame.font.SysFont("Arial", font)
        self.text=text
        self.text = self.font.render(self.text, 1, pygame.Color("blue"))
        self.change_text(bg)
 
    def change_text(self, bg="blue"):
        self.size = self.text.get_size()
        self.surface = pygame.Surface(self.size)
        self.surface.fill(bg)
        self.surface.blit(self.text, (0, 0))
        self.rect = pygame.Rect(self.x, self.y, self.size[0], self.size[1])
        
 
    def show(self):
        gameWin.blit(self.text , (self.x, self.y))
 
    def click(self, event,action):
        x, y = pygame.mouse.get_pos()
        if event.type == pygame.MOUSEBUTTONDOWN:
            if pygame.mouse.get_pressed()[0]:
                if self.rect.collidepoint(x, y):
                    if action == "quit":
                        pygame.quit()
                        quit()

                    if action == "controls":
                        controlsWin()

                    if action == "play":
                        mainGame()

                    if action == "main":
                        mainWindow()
#Creating controls window function
def controlsWin():
    
    button1 = Button("Play", (150, 500),  font=30)

    button2 = Button("Main", (350, 500), font=30)

    button3 = Button("Quit", (550, 500), font=30)
    

    while True:
        gameWin.fill('#ffffff')
        Green = (0, 255, 0)
        show_message("DataFlair Tank Game", '#000000', -200, size="large")
        show_message("Here are the instructions to play:", 'red', -100, size="medium")
        show_message("The objective is to shoot and destroy the enemy tank before they destroy you.", Green, -30)
        show_message("Fire using the Spacebar", 'gray', 0)
        show_message("Move Turret using the Up and Down arrows", Green, 30)
        show_message("Move Tank using the  Left and Right arrows", 'gray', 60)
        show_message("Press D to raise Power AND Press A to reduce Power ", Green, 90)
        show_message("Finally press P to pause", 'gray', 120)
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
            button1.click(event,'play')
            button2.click(event,'main')
            button3.click(event,'quit')
        button1.show()
        button2.show()
        button3.show()
    
        clock.tick(30)
        pygame.display.update()

#Creating main window function
def mainWindow ():
    button1 = Button("Play", (350, 350),  font=30)

    button2 = Button("Controls", (350, 430), font=30)

    button3 = Button("Quit", (350, 510), font=30)
    

    while True:
        gameWin.fill('#ffffff')
        Green = (0, 255, 0)
        show_message("electro4u tank game present", 'green', -200, size="large")
        show_message("Welcome to the game!", 'purple', -100, size="medium")
        show_message("Choose any of the following to move forward", 'purple', -50, size="medium")
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
            button1.click(event,'play')
            button2.click(event,'controls')
            button3.click(event,'quit')
        button1.show()
        button2.show()
        button3.show()
    
        clock.tick(30)
        pygame.display.update()

#Functions for game over and pause conditions
def game_over(winner):
    button1 = Button("Play Again", (350, 350),  font=30)

    button2 = Button("Controls", (350, 430), font=30)

    button3 = Button("Quit", (350, 510), font=30)
    while True:
            gameWin.fill('#ffffff')
            Green = (0, 255, 0)
            Red=(255,0,0)
            text=''
            color=''
            if(winner == 1):
                text="Contratulations, You Won!"
                color=Green
            else:
                text="Sorry, game over. Better luck next time!"
                color=Red
            show_message("DataFlair Tank Game", '#000000', -200, size="large")
            show_message(text, color, -100, size="medium")
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    pygame.quit()
                button1.click(event,'play')
                button2.click(event,'controls')
                button3.click(event,'quit')
            button1.show()
            button2.show()
            button3.show()
        
            clock.tick(30)
            pygame.display.update()

def pause():
    paused = True
    show_message("Paused", 'white', -100, size="large")
    show_message("Press C to continue playing or Q to quit", 'wheat', 25)
    pygame.display.update()
    while paused:
        #gameDisplay.fill(black)
        for event in pygame.event.get():

            if event.type == pygame.QUIT:
                pygame.quit()
                quit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_c:
                    paused = False
                elif event.key == pygame.K_q:
                    pygame.quit()
                    quit()

        clock.tick(5)

#Creating function for explosion
def explosion(x, y, size=50):
    explode = True

    while explode:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()

        startPoint = x, y

        colorChoices = ['red', 'brown2', 'yellow', 'gold1']

        magnitude = 1

        while magnitude < size:
            exploding_bit_x = x + random.randrange(-1 * magnitude, magnitude)
            exploding_bit_y = y + random.randrange(-1 * magnitude, magnitude)

            pygame.draw.circle(gameWin, colorChoices[random.randrange(0, 4)], (exploding_bit_x, exploding_bit_y),
                               random.randrange(1, 5))
            magnitude += 1

            pygame.display.update()
            clock.tick(100)

        explode = False

#Function to create the bars
def show_health_bars(player_health, enemy_health):
    if player_health > 75:
        player_color = 'green'
    elif player_health > 50:
        player_color = 'yellow'
    else:
        player_color = 'red'

    if enemy_health > 75:
        enemy_color = 'green'
    elif enemy_health > 50:
        enemy_color = 'yellow'
    else:
        enemy_color = 'red'

    pygame.draw.rect(gameWin, player_color, (680, 25, player_health, 25))
    pygame.draw.rect(gameWin, enemy_color, (20, 25, enemy_health, 25))


#Creating a function to fire by player           
def fireShell(xy, tankx, tanky, turPos, gun_power, xlocation, barrier_width, randomHeight, enemyTankX, enemyTankY):
    #pygame.mixer.Sound.play(fire_sound)
    fire = True
    damage = 0

    startingShell = list(xy)

    print("FIRE!", xy)

    while fire:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()
        pygame.draw.circle(gameWin, 'red', (startingShell[0], startingShell[1]), 5)

        startingShell[0] -= (12 - turPos) * 2

        startingShell[1] += int(
            (((startingShell[0] - xy[0]) * 0.015 / (gun_power / 50)) ** 2) - (turPos + turPos / (12 - turPos)))

        if startingShell[1] > height - groundHeight:
            print("Last shell:", startingShell[0], startingShell[1])
            hit_x = int((startingShell[0] * height - groundHeight) / startingShell[1])
            hit_y = int(height - groundHeight)
            print("Impact:", hit_x, hit_y)

            if enemyTankX + 10 > hit_x > enemyTankX - 10:
                print("Critical Hit!")
                damage = 25
            elif enemyTankX + 15 > hit_x > enemyTankX - 15:
                print("Hard Hit!")
                damage = 18
            elif enemyTankX + 25 > hit_x > enemyTankX - 25:
                print("Medium Hit")
                damage = 10
            elif enemyTankX + 35 > hit_x > enemyTankX - 35:
                print("Light Hit")
                damage = 5

            explosion(hit_x, hit_y)
            fire = False

        check_x_1 = startingShell[0] <= xlocation + barrier_width
        check_x_2 = startingShell[0] >= xlocation

        check_y_1 = startingShell[1] <= height
        check_y_2 = startingShell[1] >= height - randomHeight

        if check_x_1 and check_x_2 and check_y_1 and check_y_2:
            print("Last shell:", startingShell[0], startingShell[1])
            hit_x = int((startingShell[0]))
            hit_y = int(startingShell[1])
            print("Impact:", hit_x, hit_y)
            explosion(hit_x, hit_y)
            fire = False

        pygame.display.update()
        clock.tick(60)
    return damage

#Creating a function to fire by computer
def compfireShell(xy, tankx, tanky, turPos, gun_power, xlocation, barrier_width, randomHeight, ptankx, ptanky):
    damage = 0
    currentPower = 1
    power_found = False

    while not power_found:
        currentPower += 1
        if currentPower > 100:
            power_found = True

        fire = True
        startingShell = list(xy)

        while fire:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    pygame.quit()
                    quit()


            startingShell[0] += (12 - turPos) * 2
            startingShell[1] += int(
                (((startingShell[0] - xy[0]) * 0.015 / (currentPower / 50)) ** 2) - (turPos + turPos / (12 - turPos)))

            if startingShell[1] > height - height:
                hit_x = int((startingShell[0] * height - height) / startingShell[1])
                hit_y = int(height - height)
                if ptankx + 15 > hit_x > ptankx - 15:
                    print("target acquired!")
                    power_found = True
                fire = False

            check_x_1 = startingShell[0] <= xlocation + barrier_width
            check_x_2 = startingShell[0] >= xlocation

            check_y_1 = startingShell[1] <= height
            check_y_2 = startingShell[1] >= height - randomHeight

            if check_x_1 and check_x_2 and check_y_1 and check_y_2:
                hit_x = int((startingShell[0]))
                hit_y = int(startingShell[1])
                fire = False

    fire = True
    startingShell = list(xy)
    print("FIRE!", xy)

    while fire:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()
        pygame.draw.circle(gameWin, 'red', (startingShell[0], startingShell[1]), 5)

        startingShell[0] += (12 - turPos) * 2

        gun_power = random.randrange(int(currentPower * 0.90), int(currentPower * 1.10))

        startingShell[1] += int(
            (((startingShell[0] - xy[0]) * 0.015 / (gun_power / 50)) ** 2) - (turPos + turPos / (12 - turPos)))

        if startingShell[1] > height - groundHeight:
            print("last shell:", startingShell[0], startingShell[1])
            hit_x = int((startingShell[0] * height - groundHeight) / startingShell[1])
            hit_y = int(height - groundHeight)
            print("Impact:", hit_x, hit_y)

            if ptankx + 10 > hit_x > ptankx - 10:
                print("Critical Hit!")
                damage = 25
            elif ptankx + 15 > hit_x > ptankx - 15:
                print("Hard Hit!")
                damage = 18
            elif ptankx + 25 > hit_x > ptankx - 25:
                print("Medium Hit")
                damage = 10
            elif ptankx + 35 > hit_x > ptankx - 35:
                print("Light Hit")
                damage = 5

            explosion(hit_x, hit_y)
            fire = False

        check_x_1 = startingShell[0] <= xlocation + barrier_width
        check_x_2 = startingShell[0] >= xlocation

        check_y_1 = startingShell[1] <=height
        check_y_2 = startingShell[1] >= height - randomHeight

        if check_x_1 and check_x_2 and check_y_1 and check_y_2:
            print("Last shell:", startingShell[0], startingShell[1])
            hit_x = int((startingShell[0]))
            hit_y = int(startingShell[1])
            print("Impact:", hit_x, hit_y)
            explosion(hit_x, hit_y)
            fire = False

        pygame.display.update()
        clock.tick(60)
    return damage

#Function to create the main window
def mainGame():
    gameExit = False
    gameOver = False

    player_health = 100
    enemy_health = 100

    barrier_width = 50

    mainTankX = width * 0.9
    mainTankY = height * 0.9
    tankMove = 0
    currentTurPos = 0
    changeTur = 0

    enemyTankX = width * 0.1
    enemyTankY = height * 0.9

    fire_power = 50
    power_change = 0

    xlocation = (width / 2) + random.randint(int(-0.1 * width),int( 0.1 * width))
    randomHeight = random.randint(int(height * 0.1), int(height * 0.6))

    while True:
        gameWin.fill('#ffffff')
        Green = (0, 255, 0)
        Red=(255,0,0)
        text=''
        color=''
        show_message("DataFlair Tank Game", '#000000', -200, size="large")
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                gameExit = True
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_LEFT:
                    tankMove = -5

                elif event.key == pygame.K_RIGHT:
                    tankMove = 5

                elif event.key == pygame.K_UP:
                    changeTur = 1

                elif event.key == pygame.K_DOWN:
                    changeTur = -1

                elif event.key == pygame.K_p:
                    pause()
                elif event.key == pygame.K_SPACE:
                    gameWin.fill('white')
                    show_message("DataFlair Tank Game", '#000000', -200, size="large")
                    show_health_bars(player_health, enemy_health)
                    gun = tank(mainTankX, mainTankY, currentTurPos,1)
                    enemy_gun = tank(enemyTankX, enemyTankY, 8,-1)
                    fire_power += power_change
                    font=pygame.font.SysFont("Calibre", 30)
                    text = font.render("Power: " + str(fire_power) + "%", True, 'black')
                    gameWin.blit(text, [width / 2, 0])
                    text = font.render("Height: " + str(currentTurPos) + "%", True, 'black')
                    gameWin.blit(text, [width / 2, 20])
                    pygame.draw.rect(gameWin, 'green', [xlocation, height - randomHeight, barrier_width, randomHeight])
                    gameWin.fill('green',
                                        rect=[0,height - groundHeight, width, height])
                    pygame.display.update()

                    clock.tick(30)
                    
                    damage = fireShell(gun, mainTankX, mainTankY, currentTurPos, fire_power, xlocation, barrier_width,
                                       randomHeight, enemyTankX, enemyTankY)
                    enemy_health -= damage

                    possibleMovement = ['f', 'r']
                    moveIndex = random.randrange(0, 2)

                    for x in range(random.randrange(0, 10)):

                        if width * 0.3 > enemyTankX > width * 0.03:
                            if possibleMovement[moveIndex] == "f":
                                enemyTankX += 5
                            elif possibleMovement[moveIndex] == "r":
                                enemyTankX -= 5

                            gameWin.fill('white')
                            show_message("DataFlair Tank Game", '#000000', -200, size="large")
                            show_health_bars(player_health, enemy_health)
                            gun = tank(mainTankX, mainTankY, currentTurPos,1)
                            enemy_gun = tank(enemyTankX, enemyTankY, 8,-1)
                            fire_power += power_change
                            font=pygame.font.SysFont("Calibre", 30)
                            text = font.render("Power: " + str(fire_power) + "%", True, 'black')
                            gameWin.blit(text, [width / 2, 0])
                            text = font.render("Height: " + str(currentTurPos) + "%", True, 'black')
                            gameWin.blit(text, [width / 2, 20])
                            pygame.draw.rect(gameWin, 'green', [xlocation, height - randomHeight, barrier_width, randomHeight])
                            gameWin.fill('green',
                                             rect=[0,height - groundHeight, width, height])
                            pygame.display.update()

                            clock.tick(30)

                    damage = compfireShell(enemy_gun, enemyTankX, enemyTankY, 8, 50, xlocation, barrier_width,
                                         randomHeight, mainTankX, mainTankY)
                    player_health -= damage
                
                elif event.key == pygame.K_a:
                    power_change = -1
                elif event.key == pygame.K_d:
                    power_change = 1
                
            elif event.type == pygame.KEYUP:
                if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
                    tankMove = 0

                if event.key == pygame.K_UP or event.key == pygame.K_DOWN:
                    changeTur = 0

                if event.key == pygame.K_a or event.key == pygame.K_d:
                    power_change = 0
            

        mainTankX += tankMove

        currentTurPos += changeTur

        if currentTurPos > 8:
            currentTurPos = 8
        elif currentTurPos < 0:
            currentTurPos = 0

        if mainTankX - (tankWidth / 2) < xlocation + barrier_width:
            mainTankX += 5
    
        show_health_bars(player_health, enemy_health)
        gun = tank(mainTankX, mainTankY, currentTurPos,1)
        enemy_gun = tank(enemyTankX, enemyTankY, 8,-1)

        fire_power += power_change

        if fire_power > 100:
            fire_power = 100
        elif fire_power < 1:
            fire_power = 1
                
        font=pygame.font.SysFont("Calibre", 30)
        text = font.render("Power: " + str(fire_power) + "%", True, 'black')
        gameWin.blit(text, [width / 2, 0])
        text = font.render("Height: " + str(currentTurPos) + "%", True, 'black')
        gameWin.blit(text, [width / 2, 20])
        pygame.draw.rect(gameWin, 'green', [xlocation, height - randomHeight, barrier_width, randomHeight])
        gameWin.fill('green',rect=[0,height - groundHeight, width, height])
        if player_health < 1 :
            game_over(0)
        elif enemy_health < 1:
            game_over(1)

        pygame.display.update()
        clock.tick(30)
    

mainWindow()

BY: Balmiki Mandal

Related Blogs

Post Comments.

Login to Post a Comment

No comments yet, Be the first to comment.