space_defense.py

Created by 1epauletteshark

Created on July 30, 2024

6.59 KB


from kandinsky import *
from random import *
from math import *
from time import *
from ion import *

SCREEN_W=320
SCREEN_H=222
FONT_W=10
FONT_H=16
SPEED=10
TURN=20
FPS=20
ENEMY_COUNTDOWN=4.5
RELOAD_TIME=0.5
COLORS={"b":"black","w":"white",
        "g":"green","l":"blue",
        "r":"red","q":"gray",
        "o":"orange","y":"yellow",
        "z":color(251,255,170)}

def text(text,y=SCREEN_H/2,x=SCREEN_W/2):
  text=str(text)
  draw_string(text,int(x-len(text)*FONT_W/2),int(y-FONT_H/2),"white",color(75,0,160))
  
def move(axis,steps,dir):
  dir=radians(dir)
  if axis==x:
    return round(steps*cos(dir))
  else:
    return round(steps*sin(dir))

def render(x,y,sprite,dir=0):
  x=int(x)
  y=int(y)
  sprites={"spaceship":["0300b0400b0201b0301q0401q0501b0202b0302q0402q0502q0602b0203b0303l0403l0503l0603l0703b0104b0204b0304b0404q0504q0604q0704q0804b0005b0105l0205l0305l0405b0505q0605q0705q0805q0905b1005b1105b1205b0006b0106l0206l0306l0406q0506q0606q0706q0806q0906q1006q1106q1206l1306b1406b0107b0207b0307b0407q0507l0607l0707b0807b0907b1007q1107q1207l1307q1407l1507b0108b0208b0308q0408q0508l0608l0708b0808b0908b1008q1108q1208l1308q1408l1508b0009b0109l0209l0309l0409q0509q0609q0709q0809q0909q1009q1109q1209l1309b1409b0010b0110l0210l0310l0410b0510q0610q0710q0810q0910b1010b1110b1210b0111b0211b0311b0411l0511l0611l0711l0811b0212b0312q0412q0512q0612q0712b0213b0313q0413q0513q0613b0214b0314q0414q0514b0315b0415b",8,8],
           "bullet":["0000g0100g0200g0300g0400g0001g0101g0201g0301g0401g",2,1],
           "heart":["0200b0300b0400b0800b0900b1000b0101b0201r0301r0401r0501b0701b0801r0901r1001r1101b0002b0102r0202w0302w0402r0502r0602b0702r0802r0902r1002r1102r1202b0003b0103r0203w0303r0403r0503r0603r0703r0803r0903r1003r1103r1203b0004b0104r0204r0304r0404r0504r0604r0704r0804r0904r1004r1104r1204b0105b0205r0305r0405r0505r0605r0705r0805r0905r1005r1105b0206b0306r0406r0506r0606r0706r0806r0906r1006b0307b0407r0507r0607r0707r0807r0907b0408b0508r0608r0708r0808b0509b0609r0709b0610b",5,5],
           "explosion":["0401r0701o0901r0902r1202r1602o0303o0703o0803r0903o1003r1103o1503r0404r0704r0904o1004r1304r0505o0605r0805o0905z1005o1205r1305o1405r1705z0206r0606z0706r0806y0906z1006y1106o1206z1306r0307o0407r0607o0707o0807z0907y1007z1107z1207o1407r1507o0308r0508o0608y0708z0808y0908y1008y1108z1208y1308o0009r0209o0409o0509z0609z0709y0809z0909y1009y1109y1209z1309z1409o1609o0310r0510o0610y0710z0810y0910y1010z1110z1210o1310o1510r0311o0411r0611o0711z0811z0911y1011z1111y1211z1411r1511r0512r0612z0712o0812o0912z1012y1112o1212z1312r1612r0113r0413r0513o0813o0913z1013o1213r1413r0914o1114r1314r1414r0415o0715o0815r1015r1115o1515o0316z0616r0916o",9,9]}
  if sprite=="enemy":
    draw=sprites["spaceship"]
  else:
    draw=sprites[sprite]
  for i in range(0,len(draw[0]),5):
    pixel=draw[0][i:i+5]
    pixel_x=x-draw[1]+int(pixel[:2])
    pixel_y=y-draw[2]+int(pixel[2:4])
    if sprite=="enemy" and pixel[4]=="l":
      pixel_color="red"
    else:
      pixel_color=COLORS[pixel[4]]
    rotated_x=round((pixel_x-x)*cos(radians(dir))-(pixel_y-y)*sin(radians(dir))+x)
    rotated_y=round((pixel_x-x)*sin(radians(dir))+(pixel_y-y)*cos(radians(dir))+y)
    set_pixel(rotated_x,rotated_y,pixel_color)

def spawn_enemy():
  ex=randint(0,SCREEN_W)
  ey=randint(0,SCREEN_H)
  edir=randint(0,360)
  while not (ex>SCREEN_W or ex<0 or ey>SCREEN_H or ey<0):
    ex+=move(x,1,edir)
    ey+=move(y,1,edir)
  edir=degrees(atan2((y-ey),(x-ex)))
  ENEMIES.append({"x":ex,"y":ey,"dir":edir})

def collisions(x1,y1,size1,x2,y2,size2):
    return (
        x1<x2+size2 and
        x1+size1>x2 and
        y1<y2+size2 and
        y1+size1>y2)

while True:
  enemy_timer=monotonic()-ENEMY_COUNTDOWN
  reload_timer=monotonic()-RELOAD_TIME
  health=5
  score=0
  pause=False
  direction=-90
  ENEMY_COUNTDOWN=4.5
  x=SCREEN_W/2
  y=SCREEN_H/2
  SHOTS=[]
  ENEMIES=[]
  STARS=[[randint(0,SCREEN_W),randint(0,SCREEN_H),randint(2,8)]for _ in range(15)]
  while health>0:
    fill_rect(0,0,SCREEN_W,SCREEN_H,color(75,0,160))
    for star in STARS:
      fill_rect(star[0],star[1],int(star[2]/1.7),int(star[2]/1.7),"white")
      star[2]-=0.35
      if star[2]<=0:
        STARS[STARS.index(star)]=[randint(0,SCREEN_W),randint(0,SCREEN_H),randint(2,8)]
    for i in range(health):
      render(SCREEN_W-72+i*15,10,"heart")
    text(score,13,13)
    for bullet in SHOTS:
      bullet["x"]+=move(x,10,bullet["dir"])
      bullet["y"]+=move(y,10,bullet["dir"])
      render(bullet["x"],bullet["y"],"bullet",bullet["dir"])
      if bullet["x"]>SCREEN_W or bullet["x"]<0 or bullet["y"]>SCREEN_H or bullet["y"]<0:
        SHOTS.remove(bullet)
      else:
        for enemy in ENEMIES:
          if collisions(bullet["x"],bullet["y"],4,enemy["x"],enemy["y"],16):
            render(enemy["x"],enemy["y"],"explosion")
            ENEMIES.remove(enemy)
            SHOTS.remove(bullet)
            score+=1
            break
    render(x,y,"spaceship",direction)
    for enemy in ENEMIES:
      enemy["x"]+=move(x,6.5,enemy["dir"])
      enemy["y"]+=move(y,6.5,enemy["dir"])
      enemy["dir"]=degrees(atan2((y-enemy["y"]),(x-enemy["x"])))
      render(enemy["x"],enemy["y"],"enemy",enemy["dir"])
      if collisions(x,y,16,enemy["x"],enemy["y"],16):
        health-=1
        render(enemy["x"],enemy["y"],"explosion",randint(0,360))
        ENEMIES.remove(enemy)
    if monotonic()-enemy_timer>=ENEMY_COUNTDOWN:
      spawn_enemy()
      enemy_timer=monotonic()
    enemy_timer-=1/FPS
    if ENEMY_COUNTDOWN>2:
      ENEMY_COUNTDOWN-=0.005
    if keydown(KEY_BACKSPACE):
      text("GAME PAUSED")
      for py in range(SCREEN_H):
        for px in range(SCREEN_W):
          c=get_pixel(px,py)
          set_pixel(px,py,(c[0]-30,c[1]-30,c[2]-30))
      while not keydown(KEY_BACKSPACE):
        pass
      while keydown(KEY_BACKSPACE):
        pass
    if keydown(KEY_OK) and monotonic()-reload_timer>=RELOAD_TIME:
      SHOTS.append({"x":x,"y":y,"dir":direction})
      reload_timer=monotonic()
    if keydown(KEY_RIGHT):
      direction+=TURN
    if keydown(KEY_LEFT):
      direction-=TURN
    if keydown(KEY_UP):
      x+=move(x,SPEED,direction)
      y+=move(y,SPEED,direction)
      if x<10 or x>SCREEN_W-10 or y<10 or y>SCREEN_H-10:
        x-=move(x,SPEED,direction)
        y-=move(y,SPEED,direction)
    if keydown(KEY_DOWN):
      x-=move(x,SPEED,direction)
      y-=move(y,SPEED,direction)
      if x<0 or x>SCREEN_W or y<0 or y>SCREEN_H:
        x+=move(x,SPEED,direction)
        y+=move(y,SPEED,direction)
    sleep(1/FPS)
  render(x,y,"explosion")
  text("Game Over",SCREEN_H/2-FONT_H)
  text("You destroyed "+str(score)+" enemies!",SCREEN_H/2)
  text("[Press OK to play again]",SCREEN_H/2+FONT_H)
  while keydown(KEY_OK):
    pass
  while not keydown(KEY_OK):
    pass