Artillery Game

Software
This is a basic artillery game I wrote in python.  There are still some minor issues I need to fix, but it works and is playable.  It includes wind, movement, and variable-height (but not shape) terrain.





Here is the code:




from tkinter import *

from sys import getfilesystemencoding

import time

import random

import math


height = 600

width = 800

global t, Vo, P1Vo, P2Vo, P1A, P2A, counter,wind,active

Vo=0

t=0

Angle=0

counter=2

P1Vo=0

P1A=0

P2Vo=0

P2A=0

wind=0

active=False


##


def windspeed():

   global wind

   x=0

   for i in range(4):

      x+=random.randint(-20,20) 

   wind=x//4

   return wind


canvas = Canvas(highlightthickness=0, height=height, width=width, )

canvas.master.title("Artillery")

if getfilesystemencoding() == 'utf-8':       # only for mac

   canvas.master.call('console', 'hide')

canvas.pack()


canvas.create_rectangle(0,600,800,590,fill='green', outline='green', tag = 'ground')




class missile():

   "blows junk up"

   def __init__(self,power=Vo,angle=Angle, start=0,y=590, direction='right'):

      global t


      self.power=power

      self.angle=angle

      self.x=start

      self.y=y

      self.d=direction

      self.id = canvas.create_oval(self.x,self.y,self.x+5,self.y-5,fill='red')

   def trajectory(self,start, starty):

      "calculates the position of the missile"

      global t

      #canvas.coords(self.id,self.x,self.y,self.x+5,self.y-5)

      #canvas.create_oval(self.x,self.y,self.x+1,self.y-1)

      if self.d=='right':

         self.x=int((self.power*t*math.cos(self.angle))//1)+start

      else:

         self.x=int(-((self.power*t*math.cos(self.angle))//1))+start

      self.y=int((-(((-9.8*(t**2))//2) + (self.power*math.sin(self.angle)*t)//1))+starty)

      canvas.coords(self.id,self.x,self.y,self.x+5,self.y-5)


      t+=.005

      

class tank():

   "shoots some missiles"

   def __init__(self, pos=50,health=100,movement=100, side=10,):

      self.pos=pos

      self.side=side

      self.health=health

      self.pic=canvas.create_rectangle(self.pos, 590, self.pos+20, 580)

      self.display_health()

      self.movement=movement

      self.display=canvas.create_text(self.side+50, 50, text=(self.movement))

      self.barrel_r()

   def display_health(self):

      "displays the tank's health bar"

      self.x=canvas. create_rectangle(self.side, 20, self.side+self.health, 23, fill='red')

   def move_left(self):

      global Angle

      canvas.coords(self.pic, self.pos-2, 590, self.pos+18, 580)

      canvas.update()

      self.movement-=1

      self.pos-=2

      a_up(Angle/.0174532925)

      self.display_mov()

   def move_right(self):

      canvas.coords(self.pic, self.pos+2, 590, self.pos+22, 580)

      canvas.update()

      self.movement-=1

      self.pos+=2

      a_up(Angle/.0174532925)

      self.display_mov()

   def display_mov(self):

      "displays the amount of movement left"

      canvas.delete(self.display)

      self.display=canvas.create_text(self.side+50, 50, text=(self.movement))

   def barrel_r(self):

      global Angle

      self.b=canvas.create_line(self.pos+10, 580, 15*math.cos(Angle)+self.pos+10, 580- 15*math.sin(Angle))

      self.tip=(15*math.cos(Angle)+self.pos+10)

      self.y=(580- 15*math.sin(Angle))

      canvas.update()

   def barrel_l(self):

      global Angle

      self.b=canvas.create_line(self.pos+10, 580, 15*math.cos(Angle-(math.pi))+self.pos+10, 580- 15*math.sin(Angle))

      self.tip=(15*math.cos(Angle-(math.pi))+self.pos+10)

      self.y=(580- 15*math.sin(Angle))

      canvas.update()


class terrain():

   "a hill that is placed in the middle of the map"

   def __init__(self):

      height=random.randint(50,600)

      self.shape=canvas.create_polygon(100, 600+height, 250, 200+height, 300, 250+height,400, 0+height, 700, 600+height, fill='green')



hill=terrain()



      

wind=windspeed()

z=canvas.create_text(400,20,text=('Wind Speed: %.2d') %(wind))



tank1=tank()

tank2=tank(pos=720, side=690)


def shoot(tank, p, a):

   "animates the missile, along with lots of other stuff"

   global t,counter, P1Vo, P2Vo, P1A, P2A, Angle, Vo, tank1, tank2,wind,z,active,text, hill

   active=True

   if counter %2 ==0:

      tank=tank2

      target=tank1

   else:

      tank=tank1

      target=tank2    

   if tank==tank1:

      d='right'

   else:

      d='left'

   

   x=missile(power=p,angle=a,start=tank.tip+1, y=tank.y-3, direction=d)

   while True:

      x.x+=int((wind*t**2)/5)


      x.trajectory(start=tank.tip, starty=tank.y)


      hit=target.pos

      if (hit<= x.x <= hit+20) and 590>=x.y>=580:

         target.health-=20

         print (target.health)

         t=0

         canvas.delete(x.id)

         counter+=1

         tag=target.x

         canvas.delete(tag)

         target.display_health()

         if target.health==0:

            if target==tank1:

               player='Player 1'

            else:

               player='Player 2'

            text=canvas.create_text(400,300, text=("%s wins") % (player))

            

            canvas.update()

            break 

         break

         

      elif x.y>600 or x.x>800 or x.x<0:

         t=0

         canvas.delete(x.id)

         counter+=1

         break

      elif hill.shape in (canvas.find_overlapping(x.x, x.y, x.x+5, x.y-5)):

         canvas.delete(x.id)

         t=0

         counter+=1

         break


      time.sleep(.001):

      canvas.update()


   if counter % 2 == 0:

      p_adjuster.set(P1Vo)

      a_adjuster.set(P1A/.0174532925)


   else:

      p_adjuster.set(P2Vo)

      a_adjuster.set(P2A/.0174532925)

   wind=windspeed()

   canvas.delete(z)

   z=canvas.create_text(400,20,text=('Wind Speed: %.2d') %(wind))

   active=False





  

def keypress(event):

   global tank1, Vo, Angle, counter, P1A, P2A, P1Vo, P2Vo,active


   if not active:

      if event.keysym=="space":

         if counter % 2 == 0:

            Angle=P1A

            Vo=P1Vo

         else:

            Angle=P2A

            Vo=P2Vo


         shoot(tank1, Vo, Angle)

   if event.keysym=='Right':

      if counter %2 ==0: 

         tank=tank2

      else:

         tank=tank1

      if tank.movement > 0 and tank.pos<778:

         tank.move_right()

      else:

         pass


   elif event.keysym=='Left':

      if counter %2 ==0:

         tank=tank2

      else:

         tank=tank1

      if tank.movement > 0 and 0<tank.pos:

         tank.move_left()

      else: 

         pass


def retry(event):

   global  tank1, tank2,text,counter, P1Vo, P2Vo, P1A, P2A, hill

   counter=2

   canvas.delete(text)

   canvas.delete(tank1.pic)

   canvas.delete(tank2.pic)

   canvas.delete(tank1.b)

   canvas.delete(tank2.b)

   canvas.delete(tank1.x)

   canvas.delete(tank2.x)

   canvas.delete(tank1.display)

   canvas.delete(tank2.display)

   canvas.delete(hill.shape)

   hill=terrain()

   P1Vo, P2Vo, P1A, P2A=0, 0, 0, 0

   tank1.health=100

   tank2.health=100

   tank1=tank()

   tank2=tank(pos=720, side=690)

   p_adjuster.set(0)

   a_adjuster.set(0)




def p_up(x):

   global Vo, Angle,counter, P1Vo, P2Vo

   if counter % 2 == 0:

         P1Vo=int(x)

         Vo=P1Vo

   else:

         P2Vo=int(x)

         Vo=P2Vo

def a_up(x):

   global Vo,Angle,counter, P1A, P2A, tank1, tank2

   if counter % 2 == 0:

         P1A=int(x)*.0174532925

         Angle=P1A

         tank=tank2

         canvas.delete(tank.b)

         tank.barrel_l()

   else:

         P2A=int(x)*.0174532925

         Angle=P2A

         tank=tank1

         canvas.delete(tank.b)

         tank.barrel_r()

   



p_adjuster = Scale(canvas.master, length=400, orient=HORIZONTAL, command=p_up, from_=0, to=200, label="Power")

p_adjuster.pack(side=LEFT)

a_adjuster = Scale(canvas.master, length=400, orient=HORIZONTAL, command=a_up, from_=0, to=90, label = "Angle" )

a_adjuster.pack(side=RIGHT)

x

     

canvas.master.bind("<Key>", keypress)

canvas.master.bind("<Key-Return>", retry)



####




canvas.mainloop()





In order to run the game at a reasonable speed, it may be necessary to adjust the numbers in line 64:

"t+=.005"

or line 183:

"time.sleep(.001):"

To play, you can move your tank with the arrow keys, and press space bar to fire.  Power and angle are adjusted with the sliders.

Comments

No comments yet.

Comments are moderated and may take a little while to appear.