Copy the shortened version:
"""
INVASION OF THE TESTUDINES
v0.7.5 (minified)
By Pugmoog
"""
A6='100k point';A5='30k point';A4='fire speed+';A3='move speed';A2='fire speed';A1='orange red';A0='Score: ';z='SETUP';y=float;v=int;u=str;r='play';q='start';A='menu';n='dead';m='yellow';h='bold';f='normal';R='center';P='Arial';F=range;D=len
if z!='':import time as i,turtle as s,random as S;t=s.Turtle();T=s.getscreen();T.setup(500,500);t.tracer(0);T.bgcolor('black');t.shape('turtle');t.color(m);t.up();t.speed(0);t.ht();s.hideturtle();N=0;I=0;C=A;U=0;G=[];O=[];j=0;E=[];H=[];Q=[];J=[];B=[0 for A in F(3)];k=0;o=0;W=0;X=0;l=0;p=0;K=0;L=0;Y='';g=0;a=0;Z=[];b=[];c=[];M=[];V=[];d=[]
def A7():
global N,B,C
if C==q:C=r;return
if B[1]>0:N-=5
else:N-=2.5
def A8():
global N,B,C
if C==q:C=r;return
if B[1]>0:N+=5
else:N+=2.5
def A9():
global C
if C==r:0
elif C==A:C=q
elif C==n:C=A
T.onkey(A7,'Left')
T.onkey(A8,'Right')
T.onkey(A9,'space')
T.listen()
def e():global k,o,W;t.seth(90);t.fd(o);t.rt(90);t.fd(k)
def AA():
N='white';global I,U,V,d,L;global G,O,E,H,Q,p;global B,k,o,J;global W,X,l;global Z,b,c,M,a;t.showturtle();t.clear()
if W<=0:l=0;X=0;k=0;o=0
elif p%l==0:k=S.randint(0-X,X);o=S.randint(0-X,X)
t.seth(-90)
for A in F(D(E)):
if J[A]<=1:C=0
else:C=J[A]**(1/2.3219)
if Q[A]==f:K=255-C*40,0,0
else:K=0,255-C*20,255-C*40
t.color(K);t.goto(E[A],H[A]);e();t.seth(-90);t.down();t.stamp();t.up()
t.width(4);t.color('blue')
for A in F(D(G)):t.goto(G[A],O[A]);e();t.down();t.dot(10);t.up()
t.width(4);t.color('salmon')
for A in F(D(V)):t.goto(V[A],d[A]);e();t.down();t.dot(10);t.up()
t.seth(90);t.goto(I,-200);e();t.seth(90);t.color(m);t.stamp();t.goto(L,200);e();t.seth(90-a*90);t.color('green');t.stamp();t.color(N);t.goto(-242,225);e();t.write(A0+'{:,}'.format(U),font=(P,15,f));t.seth(90);t.color(m);t.goto(50,220);e();t.seth(90)
for A in F(D(B)):
if B[A]>0:
if A==0:t.write('FIRE SPEED BOOST '+u(v(B[A]/50)),font=(P,20,f),align=R)
elif A==1:t.write('MOVE SPEED BOOST '+u(v(B[A]/50)),font=(P,20,f),align=R)
elif A==2:t.write('MEGA FIRE SPEED BOOST '+u(v(B[A]/50)),font=(P,20,f),align=R)
t.back(35)
A+=1
for A in F(D(Z)):
t.goto(Z[A],b[A]);e()
if M[A]>20:t.color(N)
else:t.color(255,255,255,M[A]/20)
t.down();t.write('+'+c[A],font=(P,10,h),align=R);t.up()
t.hideturtle();T.update()
def AB():
global C;C=A;B=0
while C==A:
t.clear();t.color(m);t.goto(0,100);t.write('INVASION OF THE TESTUDINES',font=(P,20,h),align=R);t.goto(0,0)
if B%2==0:t.write('PRESS [SPACE] TO PLAY',font=(P,20,h),align=R)
t.color(A1);t.goto(0,-230);t.write('IN GAME, USE [ARROW KEYS] TO MOVE',font=(P,15,h),align=R);T.update();i.sleep(.5);B+=1
def w():
global E,H,Q,J;E=[];H=[];Q=[];J=[];B=12;G=5;A=30;C=0-B*(A-1)/2;D=200
for I in F(G):
for I in F(B):
E.append(C);H.append(D)
if K==1:Q.append(f);J.append(1)
elif S.randint(1,500//K**1.3)==1:Q.append('shoot');J.append(S.randint(1,K*3))
elif S.randint(1,100//K**1.4)==1:Q.append(f);J.append(S.randint(1,K*3))
else:Q.append(f);J.append(1)
C+=A
C=0-B*(A-1)/2;D-=A
def AC():
global L,g,Y,a;global K,I,C,U,V,d;global G,O,E,H;global B,J,k,AF;global Z,b,c,M;global W,X,l
for A in F(D(G)):O[A]+=10
A=0
for A in F(D(E)):H[A]-=.1+.05*K
for A in F(D(V)):d[A]-=5
L+=.3*a
if D(E)==0:w();K+=1;G=[];O=[]
for A in F(D(G)):
if L-25<G[A]<L+25 and 175<O[A]<225:
G[A]=-69420.8008;g-=1
if g<1:
g=9999999;W=24;X=10;l=2
if Y==A2:
if B[0]>0:B[0]+=1000
else:B[0]=1000
elif Y==A3:
if B[1]>0:B[1]+=1000
else:B[1]=1000
elif Y==A4:
if B[2]>0:B[2]+=500
else:B[2]=500
elif Y==A5:U+=30000;Z.append(L);b.append(200);M.append(200);c.append('30k')
elif Y==A6:U+=100000;Z.append(L);b.append(200);M.append(200);c.append('100k')
L=999999999
for A in F(D(G)):
if O[A]>250:G[A]=-69420.8008
A+=1
for A in F(D(E)):
for N in F(D(G)):
if-2e1<E[A]-y(G[N])<2e1 and-25.<H[A]-y(O[N])<25.:
G[N]=-69420.8008;J[A]-=1
if J[A]<1:Z.append(E[A]);b.append(H[A]+20);M.append(20);c.append('100');E[A]=-69420.8008;U+=100
W=6;X=2;l=1
for A in F(D(V)):
if-15<I-V[A]<15 and-20<-200-d[A]<20:C=n
for A in F(D(E)):
if H[A]<-240 or I-25<E[A]<I+25 and-225<H[A]<-175:C=n
A=0
while A!=D(G):
if G[A]==-69420.8008:O.pop(A);G.pop(A)
else:A+=1
A=0
while A!=D(E):
if E[A]==-69420.8008:H.pop(A);E.pop(A);Q.pop(A);J.pop(A)
else:A+=1
def AD():
global C,U;C=n;t.color(m);t.goto(0,100);t.write('GAME OVER',font=(P,20,h),align=R);t.goto(0,0);t.write('PRESS [SPACE] TO CONTINUE',font=(P,20,h),align=R);t.goto(0,-100);t.write(A0+'{:,}'.format(U),font=(P,20,'italic'),align=R);T.update();i.sleep(.5)
while C==n:0
def AE(items,weights):
A=weights;E=sum(A);G=S.randint(1,E);B=0
for C in F(D(A)):
B+=A[C]
if G<=B:return items[C]
def x():
if z!='':global L,g,Y,a;global K,p,I,C,N,U,j;global G,O,E,H,Q,W;global B,V,d;global Z,b,c,M;AB();U=0;K=1;w();p=0;N=0;I=0;B=[0 for A in B];l=0;o=0;W=0;s=0;u=0;L=99999;Y='';g=99999;a=0;G=[];O=[];V=[];d=[]
C=q;t.clear();t.goto(0,0);t.color(A1);t.write('USE ARROW KEYS TO MOVE',font=(P,20,h),align=R);t.goto(I,-200);t.color(m);t.seth(90);t.stamp();T.update()
while C==q:0
C=r;J=i.time()
while True:
p+=1;J=i.time();j-=1;W-=1
for A in F(D(B)):B[A]-=1
N*=.85;I+=N
if not-250<I<250:I-=N;N=0
if j<0:
if B[2]>0:j=0
elif B[0]>0:j=2
else:j=10
G.append(I);O.append(-200)
for A in F(D(E)):
if Q[A]=='shoot'and S.randint(1,1000//K)==1:V.append(E[A]);d.append(H[A])
if abs(L)>300 and S.randint(1,1000//K)==1:a=S.randint(0,1)*2-1;L=-300*a;g=round(5-1/K*10);e=[A5,A6,A2,A4,A3];f=[10,5,15,5,7];Y=AE(e,weights=f)
for A in F(D(M)):M[A]-=1
A=0
while A!=D(M):
if M[A]<=0:M.pop(A);Z.pop(A);b.pop(A);c.pop(A)
else:A+=1
AA();AC()
if C==n:AD();x()
k=i.time();X=k-J
if X<.015:i.sleep(.015-X)
x()
Or copy the commented version:
"""
INVASION OF THE TESTUDINES
v0.7.5
By Pugmoog
"""
if "SETUP"!="":
import time
import turtle
import random
# setup
t = turtle.Turtle()
screen = turtle.getscreen()
screen.setup(500, 500)
t.tracer(0)
screen.bgcolor("black")
t.shape("turtle")
t.color("yellow")
t.up()
t.speed(0)
t.ht()
turtle.hideturtle()
# setup variables
spd_x = 0
pos_x = 0
state = "menu"
score = 0
bullet_x = []
bullet_y = []
shoot_cooldown = 0
enemy_x = []
enemy_y = []
enemy_type = []
enemy_health = []
powerup_cooldowns = [0 for _ in range(3)]
screenshake_x = 0
screenshake_y = 0
screenshake_time = 0
screenshake_intensity = 0
screenshake_delay = 0
game_tick = 0
level = 0
flyover_x = 0
flyover_type = ""
flyover_health = 0
flyover_direction = 0
point_msg_x = []
point_msg_y = []
point_msg_amt = []
point_msg_timer = []
enemy_bullet_x = []
enemy_bullet_y = []
'''--------------------------------'''
'''--------------------------------'''
# take input
def left():
global spd_x, powerup_cooldowns, state
if state == "start":
state = "play"
return
if powerup_cooldowns[1] > 0:
spd_x -= 5
else:
spd_x -= 2.5
def right():
global spd_x, powerup_cooldowns, state
if state == "start":
state = "play"
return
if powerup_cooldowns[1] > 0:
spd_x += 5
else:
spd_x += 2.5
def space():
global state
if state == "play":
pass
elif state == "menu":
state = "start"
elif state == "dead":
state = "menu"
screen.onkey(left, "Left")
screen.onkey(right, "Right")
screen.onkey(space, "space")
screen.listen()
'''--------------------------------'''
'''--------------------------------'''
def apply_screenshake():
global screenshake_x, screenshake_y, screenshake_time
t.seth(90)
t.fd(screenshake_y)
t.rt(90)
t.fd(screenshake_x)
def draw():
global pos_x, score, enemy_bullet_x, enemy_bullet_y, flyover_x
global bullet_x, bullet_y, enemy_x, enemy_y, enemy_type, game_tick
global powerup_cooldowns, screenshake_x, screenshake_y, enemy_health
global screenshake_time, screenshake_intensity, screenshake_delay
global point_msg_x, point_msg_y, point_msg_amt, point_msg_timer, flyover_direction
t.showturtle()
t.clear()
if screenshake_time <= 0:
screenshake_delay = 0
screenshake_intensity = 0
screenshake_x = 0
screenshake_y = 0
elif game_tick % screenshake_delay == 0:
screenshake_x = random.randint(0-screenshake_intensity, screenshake_intensity)
screenshake_y = random.randint(0-screenshake_intensity, screenshake_intensity)
# draw enemies, one by one
t.seth(-90)
for i in range( len(enemy_x) ):
if enemy_health[i] <= 1:
number = 0
else:
number = enemy_health[i] ** (1 / 2.3219)
if enemy_type[i] == "normal":
color = ( 255-(number*40) , 0, 0)
else:
color = (0, 255-(number*20), 255-(number*40))
t.color(color)
t.goto(enemy_x[i], enemy_y[i])
apply_screenshake()
t.seth(-90)
t.down()
t.stamp()
t.up()
# draw bullets, one by one
t.width(4)
t.color("blue")
for i in range( len(bullet_x) ):
t.goto(bullet_x[i], bullet_y[i])
apply_screenshake()
t.down()
t.dot(10)
t.up()
# draw enemy bullets, one by one
t.width(4)
t.color("salmon")
for i in range( len(enemy_bullet_x) ):
t.goto(enemy_bullet_x[i], enemy_bullet_y[i])
apply_screenshake()
t.down()
t.dot(10)
t.up()
# draw player
t.seth(90)
t.goto(pos_x, -200)
apply_screenshake()
t.seth(90)
t.color("yellow")
t.stamp()
# draw flyovers
t.goto(flyover_x, 200)
apply_screenshake()
t.seth(90 - (flyover_direction * 90))
t.color("green")
t.stamp()
# write score in top right
t.color("white")
t.goto(-242, 225)
apply_screenshake()
t.write("Score: "+("{:,}".format(score)), font=("Arial", 15, "normal"))
# notify player if they got a powerup
t.seth(90)
t.color("yellow")
t.goto(50, 220)
apply_screenshake()
t.seth(90)
for i in range(len(powerup_cooldowns)):
if powerup_cooldowns[i] > 0:
if i == 0:
t.write("FIRE SPEED BOOST "+str(int(powerup_cooldowns[i]/50)), font=("Arial", 20, "normal"), align="center")
elif i == 1:
t.write("MOVE SPEED BOOST "+str(int(powerup_cooldowns[i]/50)), font=("Arial", 20, "normal"), align="center")
elif i == 2:
t.write("MEGA FIRE SPEED BOOST "+str(int(powerup_cooldowns[i]/50)), font=("Arial", 20, "normal"), align="center")
t.back(35)
i += 1
# notify player if they gained points
for i in range(len(point_msg_x)):
t.goto(point_msg_x[i], point_msg_y[i])
apply_screenshake()
if point_msg_timer[i] > 20:
t.color("white")
else:
t.color(255, 255, 255, point_msg_timer[i]/20)
t.down()
t.write("+"+point_msg_amt[i], font=("Arial", 10, "bold"), align="center")
t.up()
# hide and update
t.hideturtle()
screen.update()
def title_screen():
global state
state = "menu"
tick = 0
# Show text until player presses space
while state == "menu":
t.clear()
t.color("yellow")
t.goto(0, 100)
t.write("INVASION OF THE TESTUDINES", font=("Arial", 20, "bold"), align="center")
t.goto(0, 0)
if tick % 2 == 0:
t.write("PRESS [SPACE] TO PLAY", font=("Arial", 20, "bold"), align="center")
t.color("orange red")
t.goto(0, -230)
t.write("IN GAME, USE [ARROW KEYS] TO MOVE", font=("Arial", 15, "bold"), align="center")
screen.update()
time.sleep(0.5)
tick += 1
def spawn_enemies():
global enemy_x, enemy_y, enemy_type, enemy_health
enemy_x = []
enemy_y = []
enemy_type = []
enemy_health = []
width = 12
height = 5
spacing = 30
x = 0 - (width*(spacing-1) / 2)
y = 200
for _ in range(height):
for _ in range(width):
enemy_x.append(x)
enemy_y.append(y)
if level == 1: # level 1 normal
enemy_type.append("normal")
enemy_health.append(1)
elif random.randint(1, 500//(level**1.3)) == 1: # blue shooting turtles
enemy_type.append("shoot")
enemy_health.append(random.randint(1, level*3))
elif random.randint(1, 100//(level**1.4)) == 1: # higher health normals
enemy_type.append("normal")
enemy_health.append(random.randint(1, level*3))
else: # give up and do normal
enemy_type.append("normal")
enemy_health.append(1)
x += spacing
x = 0 - (width*(spacing-1) / 2)
y -= spacing
def update_enemies_and_bullets():
global flyover_x, flyover_health, flyover_type, flyover_direction
global level, pos_x, state, score, enemy_bullet_x, enemy_bullet_y
global bullet_x, bullet_y, enemy_x, enemy_y
global powerup_cooldowns, enemy_health, screenshake_x, screenshske_y
global point_msg_x, point_msg_y, point_msg_amt, point_msg_timer
global screenshake_time, screenshake_intensity, screenshake_delay
# move forward bullets
for i in range( len(bullet_x) ):
bullet_y[i] += 10
i = 0
# move forward enemies
for i in range( len(enemy_x) ):
enemy_y[i] -= 0.1 + (0.05 * level)
# move forward enemy bullets
for i in range(len(enemy_bullet_x)):
enemy_bullet_y[i] -= 5
# move flyovers
flyover_x += 0.3 * flyover_direction
# respawn enemies if they all die
if len(enemy_x) == 0:
spawn_enemies()
level += 1
bullet_x = []
bullet_y = []
#-------------------------------
# flyover collision
for i in range( len(bullet_x) ):
if flyover_x-25 < bullet_x[i] < flyover_x+25 and 175 < bullet_y[i] < 225:
bullet_x[i] = -69420.8008
flyover_health -= 1
if flyover_health < 1:
flyover_health = 9999999
screenshake_time = 24
screenshake_intensity = 10
screenshake_delay = 2
if flyover_type == "fire speed":
if powerup_cooldowns[0] > 0:
powerup_cooldowns[0] += 1000
else:
powerup_cooldowns[0] = 1000
elif flyover_type == "move speed":
if powerup_cooldowns[1] > 0:
powerup_cooldowns[1] += 1000
else:
powerup_cooldowns[1] = 1000
elif flyover_type == "fire speed+":
if powerup_cooldowns[2] > 0:
powerup_cooldowns[2] += 500
else:
powerup_cooldowns[2] = 500
elif flyover_type == "30k point":
score += 30000
point_msg_x.append(flyover_x)
point_msg_y.append(200)
point_msg_timer.append(200)
point_msg_amt.append("30k")
elif flyover_type == "100k point":
score += 100000
point_msg_x.append(flyover_x)
point_msg_y.append(200)
point_msg_timer.append(200)
point_msg_amt.append("100k")
flyover_x = 999999999
# delete bullets if they reach the end
for i in range( len(bullet_x) ):
if bullet_y[i] > 250:
bullet_x[i] = -69420.8008
i += 1
# delete enemy and bullet if they collide
for i in range( len(enemy_x) ):
for j in range( len(bullet_x) ):
if -20.0 < enemy_x[i]-float(bullet_x[j]) < 20.0 and -25.0 < enemy_y[i]-float(bullet_y[j]) < 25.0:
bullet_x[j] = -69420.8008
enemy_health[i] -= 1
if enemy_health[i] < 1:
point_msg_x.append(enemy_x[i])
point_msg_y.append(enemy_y[i]+20)
point_msg_timer.append(20)
point_msg_amt.append("100")
enemy_x[i] = -69420.8008
score += 100
screenshake_time = 6
screenshake_intensity = 2
screenshake_delay = 1
# lose if player and enemy bullet collide
for i in range(len(enemy_bullet_x)):
if -15 < pos_x-enemy_bullet_x[i] < 15 and -20 < -200-enemy_bullet_y[i] < 20:
state = "dead"
# lose if enemy reaches the end or touches player
for i in range(len(enemy_x)):
if enemy_y[i] < -240 or ((pos_x-25 < enemy_x[i] < pos_x+25) and (-225 < enemy_y[i] < -175)):
state = "dead"
#-------------------------------
# actually delete the enemies and bullets
i = 0
while i != len(bullet_x):
if bullet_x[i] == -69420.8008:
bullet_y.pop(i)
bullet_x.pop(i)
else:
i += 1
i = 0
while i != len(enemy_x):
if enemy_x[i] == -69420.8008:
enemy_y.pop(i)
enemy_x.pop(i)
enemy_type.pop(i)
enemy_health.pop(i)
else:
i += 1
def die():
global state, score
state = "dead"
# Show text until player presses space
t.color("yellow")
t.goto(0, 100)
t.write("GAME OVER", font=("Arial", 20, "bold"), align="center")
t.goto(0, 0)
t.write("PRESS [SPACE] TO CONTINUE", font=("Arial", 20, "bold"), align="center")
t.goto(0, -100)
t.write("Score: "+("{:,}".format(score)), font=("Arial", 20, "italic"), align="center")
screen.update()
time.sleep(0.5)
while state == "dead":
pass
def weighted_choice(items, weights):
weight_sum = sum(weights)
rand_num = random.randint(1, weight_sum)
running_sum = 0
for i in range(len(weights)):
running_sum += weights[i]
if rand_num <= running_sum:
return items[i]
'''--------------------------------'''
'''--------------------------------'''
# main game loop
def play():
if "SETUP"!="":
global flyover_x, flyover_health, flyover_type, flyover_direction
global level, game_tick, pos_x, state, spd_x, score, shoot_cooldown
global bullet_x, bullet_y, enemy_x, enemy_y, enemy_type, screenshake_time
global powerup_cooldowns, enemy_bullet_x, enemy_bullet_y
global point_msg_x, point_msg_y, point_msg_amt, point_msg_timer
title_screen()
score = 0
level = 1
spawn_enemies()
game_tick = 0
spd_x = 0
pos_x = 0
powerup_cooldowns = [0 for _ in powerup_cooldowns]
screenshake_x = 0
screenshake_y = 0
screenshake_time = 0
screenshake_intensity = 0
screenshake_delay = 0
flyover_x = 99999
flyover_type = ""
flyover_health = 99999
flyover_direction = 0
bullet_x = []
bullet_y = []
enemy_bullet_x = []
enemy_bullet_y = []
state = "start"
t.clear()
t.goto(0,0)
t.color("orange red")
t.write("USE ARROW KEYS TO MOVE", font=("Arial", 20, "bold"), align="center")
t.goto(pos_x, -200)
t.color("yellow")
t.seth(90)
t.stamp()
screen.update()
while state == "start": pass
state = "play"
time_before_frame = time.time()
while True:
game_tick += 1
time_before_frame = time.time()
shoot_cooldown -= 1
screenshake_time -= 1
# tick cooldown timers for powerups
for i in range( len(powerup_cooldowns) ):
powerup_cooldowns[i] -= 1
# physics
spd_x *= 0.85
pos_x += spd_x
if not -250 < pos_x < 250:
pos_x -= spd_x
spd_x = 0
# shoot bullets
if shoot_cooldown < 0:
if powerup_cooldowns[2] > 0:
shoot_cooldown = 0
elif powerup_cooldowns[0] > 0:
shoot_cooldown = 2
else:
shoot_cooldown = 10
bullet_x.append(pos_x)
bullet_y.append(-200)
# enemy shoot bullets
for i in range(len(enemy_x)):
if enemy_type[i] == "shoot" and random.randint(1, 1000//level) == 1:
enemy_bullet_x.append(enemy_x[i])
enemy_bullet_y.append(enemy_y[i])
# spawn flyovers
if abs(flyover_x) > 300 and random.randint(1, 1000//level) == 1:
flyover_direction = random.randint(0,1) * 2 - 1
flyover_x = -300 * flyover_direction
flyover_health = round( 5-(1/level) * 10 )
options = ["30k point", "100k point", "fire speed", "fire speed+", "move speed"]
weights = [10, 5, 15, 5, 7]
flyover_type = weighted_choice(options, weights=weights)
# update point messages
for i in range(len(point_msg_timer)):
point_msg_timer[i] -= 1
i = 0
while i != len(point_msg_timer):
if point_msg_timer[i] <= 0:
point_msg_timer.pop(i)
point_msg_x.pop(i)
point_msg_y.pop(i)
point_msg_amt.pop(i)
else:
i += 1
# draw
draw()
# update enemies and bullets
update_enemies_and_bullets()
# end game if enemies reached the end
if state == "dead":
die()
play()
# if game is running too fast, slow down
time_after_frame = time.time()
time_frame_took = time_after_frame - time_before_frame
if time_frame_took < 0.015:
time.sleep(0.015 - time_frame_took)
play()