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.
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.
No comments:
Post a Comment