Ok here it is..
setup for a 800x800 windows so change size & onScreen if you want bigger smaller.
control "tank" with arrow keys and fire with x.
import random,pygame,time, math
from pygame.locals import *
def countdown(item):
item[5]-=time_passed
item[9]-=time_passed
if item[5]<0:item[5]=0
if item[9]<0:item[9]=0
def offscreen(item):
if item[1]<0 or item[1]>(size-item[7]) or item[2]<0 or item[2]>(size-item[8]):
return 1
def turn(item):
v=[]
v.append([item[4],item[3]])
v.append([item[4]*-1,item[3]*-1])
u=random.randint(0,len(v)-1)
item[3]=v[u][0]
item[4]=v[u][1]
item[1]=item[10]
item[2]=item[11]
def doCollision(no,item,type): #[j,wave[j],processor[1]
if(type==1): # item stop
item[1]=item[10]
item[2]=item[11]
item[3]=0
item[4]=0
elif(type==2): # item explode
kill[no]=1
wave.append([13,item[1],item[2],0,0,400,3,item[7],item[8],0,0,0])
elif(type==3): # item reverse
item[3]*=-1
item[4]*=-1
elif(type==4): # wrap around screen
if item[1]<0:item[1]=(size-item[7])
elif item[1]>(size-item[7]):item[1]=0
elif item[2]<0:item[2]=(size-item[8])
elif item[2]>(size-item[7]):item[2]=0
elif(type==5): # item turn
turn(item)
def makeEnemy(delay):
c=[0,0]
b=random.randint(0,1)
sizetmp=size-20
c[b]=random.randint(0,sizetmp)
c[not b]=random.randint(0,1)*sizetmp
x=c[0]
y=c[1]
v=[]
if x==0:v.append([1,0])
elif x==sizetmp:v.append([-1,0])
if y==0:v.append([0 ,1])
elif y==sizetmp:v.append([0,-1])
d=random.randint(0,len(v)-1)
s=random.randint(60,70)
side=random.randint(6,25)
return [11,x,y,v[d][0],v[d][1],0,s,side,side,delay,x,y] # 0-type,1-x,2-y,3-vx,4-vy,5-life in ms,6-speed,7-sizex, 8-sizey, 9-collsion delay, 10-last safe x, 11- last safe y
no_enemies=20
size=800
onScreen=800
wave=[]
wave.append([1,size/2,size/2,0,-1,9999,2,25,25,25,100,50,50]) #player
wave.append([15,100,80,0,0,1000,0,100,50,0,0,0]) #wall
wave.append([15,50,180,0,0,9999,0,50,100,0,0,0]) # 11- enemy, 12- shell, 13- explosion, 15- wall.
wave.append([15,300,150,0,0,9999,0,50,200,0,0,0])
wave.append([15,100,330,0,0,9999,0,170,50,0,0,0])
ignoreCollision={(13,13):1,(13,12):1,(12,13):1,(13,15):1,(15,13):1,(15,15):1}
processCollision={(15,1):(0,1),(1,15):(1,0),(11,15):(5,0),(15,11):(0,5),(12,15):(2,0),(15,12):(0,2),(1,99):(4,0),(13,99):(0,0),(11,99):(4,0),(12,99):(2,0)} # 0 - nothing, 1 - stop, 2 - explode, 3 - reverse, 4 - wrap
for j in range(no_enemies):wave.append(makeEnemy(200))
reloading=3
pygame.init()
main_surface=pygame.display.set_mode((onScreen,onScreen))
clock=pygame.time.Clock()
while 1:
time_passed=clock.tick(60)
dtime=time_passed/1000
screen=pygame.Surface((size,size))
for i in range(len(wave)-1,-1,-1):
typ=wave[i][0] # what is item type ?
countdown(wave[i]) # reduce life and collision delay timers if they above 0.
m=int(wave[i][7]/2)
if typ==12 or typ==13: # only shells or explosions have a set lifespan
if not wave[i][5]:
del wave[i]
continue
if typ==11: # enemy randomly fire in random directions
if random.randint(0,500)>497:
wave.append([12,wave[i][1]+m,wave[i][2]+m,random.randint(-1,1),random.randint(-1,1),2000,150,3,3,200,0,0])
if random.randint(0,500)>498: #and randomly turns
turn(wave[i])
if typ==13: # explosions expand
wave[i][7]+=1*60*dtime
wave[i][8]+=1*60*dtime
wave[i][1]-=1*30*dtime
wave[i][2]-=1*30*dtime
if typ==1: # ie player
reloading-=time_passed
pressed = pygame.key.get_pressed()
v=[0,0]
if pressed[pygame.K_RIGHT]:v[0]=1
if pressed[pygame.K_LEFT]:v[0]=-1
if pressed[pygame.K_UP]:v[1]=-1
if pressed[pygame.K_DOWN]:v[1]=1
if v[0] or v[1]:
wave[i][3]=v[0]
wave[i][4]=v[1]
wave[i][10]=wave[i][1]
wave[i][11]=wave[i][2]
wave[i][1]+=int(v[0]*dtime*150)
wave[i][2]+=int(v[1]*dtime*150)
if pressed[pygame.K_x]:
if reloading<0:
wave.append([12,wave[i][1]+m,wave[i][2]+m,wave[i][3],wave[i][4],1000,300,3,3,100,0,0])
reloading=80
else:
wave[i][10]=wave[i][1]
wave[i][11]=wave[i][2]
wave[i][1]+=int(wave[i][6]*wave[i][3]*dtime) # move x i.e 50 pixels per second. * direction -1 * 0.017
wave[i][2]+=int(wave[i][6]*wave[i][4]*dtime) # move y
if random.randint(0,1000)>999:
wave.append(makeEnemy(200))
if not wave[i][9]:
if typ==13:
pygame.draw.ellipse(screen,(255,0,0), (wave[i][1],wave[i][2],wave[i][7],wave[i][8]),1)
else:
pygame.draw.rect(screen,(255,255,255),(wave[i][1],wave[i][2],wave[i][7],wave[i][8]),1)
if typ==1: # ie player
pygame.draw.line(screen,(255,255,255),(wave[i][1]+m,wave[i][2]+m),(wave[i][1]+m+(wave[i][3]*17),wave[i][2]+m+(wave[i][4]*17)))
kill={}
for i in range(len(wave)-1,-1,-1):
if offscreen(wave[i]):
processor=processCollision.get((wave[i][0],99))## doCollision(i,wave[i],processor)
doCollision(i,wave[i],processor[0])
else: # if item is not offscreen then check for collsions against everything else.
for j in range(i-1,-1,-1): # player position 0 will only ever feature in j
if wave[j][9] or wave[i][9]:continue # if either item is still in a collision delay skip.
if (wave[i][0],wave[j][0]) in ignoreCollision: # we are not interested in some collisions.ie explosions with explosions Don't bother with any further processing
continue
if wave[j][1]<wave[i][1]+wave[i][7]:#1x<2x+2s
if wave[j][1]+wave[j][7]>wave[i][1]:#1x+1s>2x
if wave[j][2]<wave[i][2]+wave[i][8]:#1y<2y+2s
if wave[j][2]+wave[j][8]>wave[i][2]:#1y+1s>2y
if (wave[i][0],wave[j][0]) in processCollision: # if we dont have a processor for this combination of items colliding kill both of them
processor=processCollision.get((wave[i][0],wave[j][0]))
doCollision(i,wave[i],processor[0])
doCollision(j,wave[j],processor[1])
else:
kill[i]=1
kill[j]=1
wave.append([13,wave[j][1],wave[j][2],0,0,1000,3,wave[j][7],wave[j][8],0,0,0])
break # doesn't consider 3 way
for k in reversed(sorted(kill.keys())):
del wave[k]
screen=pygame.transform.scale(screen,(onScreen,onScreen))
main_surface.blit(screen, (0,0))
pygame.display.flip()
pygame.event.pump()