I should have made this a repo a while ago

This commit is contained in:
Zergling_man 2024-12-15 12:30:05 +11:00
commit 61b3e77c07
7 changed files with 250 additions and 0 deletions

10
enemy.py Normal file
View File

@ -0,0 +1,10 @@
import pygame
class Enemy():
def __init__(self,x,y):
self.x,self.y=x,y
def draw(self,screen):
pygame.draw.circle(screen,'black',(self.x,self.y),8)
def update(self,events): pass

41
game.py Normal file
View File

@ -0,0 +1,41 @@
import pygame
pygame.init()
import grid as grod
import workers
import ring
running=False
objs=[]
def main():
screen=pygame.display.set_mode((1280,720))
clock=pygame.time.Clock()
global running; running=True
act=0
grid=grod.Grid(8,8,64,12,11)
grid.add_worker(workers.behaviours.Cursor)
grid.add_worker(workers.behaviours.Average)
grid.add_tower(5,5)
grid.add_tower(3,4,'cannon',2)
objs.append(grid)
while running:
update()
draw(screen)
clock.tick(60)
pygame.quit()
def update():
events=pygame.event.get()
for event in events:
if event.type==pygame.QUIT: global running; running=False
if event.type==pygame.KEYDOWN: print(event)
for obj in objs:
obj.update(events)
def draw(screen):
screen.fill((64,128,64))
for obj in objs:
obj.draw(screen)
pygame.display.flip()
main()

80
grid.py Normal file
View File

@ -0,0 +1,80 @@
import pygame
import workers, towers, ring
import random
boxcols=[(90,90,90),(128,0,0),(0,128,0),(0,0,128)]
class Grid():
def __init__(self,x,y,spacing,w,h):
self.x,self.y,self.spacing,self.w,self.h=x,y,spacing,w,h
self.xe,self.ye=x+spacing*w,y+spacing*h
self.highlight=None
self.act=0
self.menu=None
self.mx,self.my=0,0
self.towers=[] # I'll make this a property later
self.workers=[]
def cell(self,x,y):
sx,sy,s,w,h=self.x,self.y,self.spacing,self.w,self.h
if not (sx<x<sx+s*w and sy<y<sy+s*h): return None
x-=sx; y-=sy
return x//s,y//s
def cell_to_real(self,x,y):
if not (0<x<self.w and 0<y<self.h): return 0,0,0
s=self.spacing
return self.x+s*x,self.y+s*y,s
def add_tower(self,x,y,*args):
self.towers.append(towers.Tower(x,y,self,*args))
self.calc_tower_mean()
def add_worker(self,behaviour):
self.workers.append(workers.Worker(int(random.random()*self.spacing*self.w+self.y),int(random.random()*self.spacing*self.h+self.y),behaviour,self))
def calc_tower_mean(self):
coords=list(map(lambda x:(x.x,x.y),self.towers))
x=list(map(lambda x:x[0],coords))
y=list(map(lambda x:x[1],coords))
x=sum(x)/len(x); y=sum(y)/len(y)
mx,my,offset=self.cell_to_real(x,y)
self.mx,self.my=mx+offset/2,my+offset/2
def draw(self,screen):
x,y,s,w,h=self.x,self.y,self.spacing,self.w,self.h
xe,ye=self.xe,self.ye
pygame.draw.rect(screen,(90,90,45),(x,y,s*w,s*h))
for i in range(h+1):
pygame.draw.line(screen,'black',(x,i*s+y),(xe,i*s+y))
for i in range(w+1):
pygame.draw.line(screen,'black',(i*s+x,y),(i*s+x,ye))
for tower in self.towers: tower.draw(screen)
if self.highlight is not None:
hx,hy,_=self.cell_to_real(*self.highlight)
hl=pygame.Surface((s,s))
hl.set_alpha(128)
pygame.draw.rect(hl,boxcols[self.act],(0,0,s,s))
screen.blit(hl,(hx,hy))
for worker in self.workers: worker.draw(screen)
if self.menu: self.menu.draw(screen)
def update(self,events):
x,y=pygame.mouse.get_pos()
if not self.act:
self.highlight=self.cell(x,y)
if self.menu: self.menu=None
elif self.menu is None and self.highlight is not None:
self.menu=ring.Ring(x,y,self.spacing*2.5,[ring_wrap(self,'cannon',0),ring_wrap(self,'cannon',1),ring_wrap(self,'cannon',2),ring_wrap(self,'cannon',3)],self)
for event in events:
if event.type==pygame.KEYUP: self.act=0; continue
if event.type!=pygame.KEYDOWN: continue
if event.scancode not in [4,7,22]: continue
self.act={4:1,22:2,7:3}[event.scancode]
for tower in self.towers: tower.update(events)
for worker in self.workers: worker.update(events)
if self.menu: self.menu.update(events)
def ring_wrap(grid,ttype,elem):
def ring_inner(x,y):
grid.add_tower(*grid.cell(x,y),ttype,elem)
return ring_inner

34
ring.py Normal file
View File

@ -0,0 +1,34 @@
import pygame
import math
thpi=math.pi/3
import utils
colours=[(196,0,0),(0,196,0),(0,0,196)]
class Ring():
def __init__(self,x,y,size,actions,grid):
self.x,self.y,self.size,self.grid=x,y,size,grid
self.init=0
self.selected=-1
self.actions=actions
self.width=2*math.pi/len(self.actions)
def draw(self,screen):
offset=self.size*self.init*0.5
l=len(self.actions)
for i in range(l,0,-1):
i-=1
colour=colours[i%len(colours)]
if i==len(colours) and 0==utils.sign((l-1)%3): colour=colours[1]
if i==self.selected: colour=tuple(n/2 for n in colour)
pygame.draw.arc(screen,colour,(self.x-offset,self.y-offset,offset*2,offset*2),-(i+1)*self.width,-i*self.width,int(offset*2/3))
def update(self,events):
if self.init<1: self.init+=0.05
else: self.init=1
self.selected=int(utils.get_direction(self.x,self.y,*pygame.mouse.get_pos())//self.width%len(self.actions))
mx,my=pygame.mouse.get_pos()
if ((self.y-my)**2+(self.x-mx)**2)**0.5<self.size/6: self.selected=-1
def __del__(self):
if self.selected>-1: self.actions[self.selected](self.x,self.y)

45
towers.py Normal file
View File

@ -0,0 +1,45 @@
import pygame
class Tower():
def __init__(self,x,y,grid,ttype='null',elem=0):
self.x,self.y,self.grid=x,y,grid
self.type=ttype
self.elem=elem
self.target=Mouse()
def draw(self,screen):
x,y,s=self.grid.cell_to_real(self.x,self.y)
sprites.get(self.type,'null')(screen,x,y,s,self)
def update(self,events):
self.target.update(events)
if self.target: self.tx,self.ty=self.target.x,self.target.y
class Mouse():
def update(self,events):
self.x,self.y=pygame.mouse.get_pos()
shots={}
def mkshot(funky):
shots[funky.__name__]=funky
return funky
sprites={}
def mksprite(funky):
sprites[funky.__name__]=funky
return funky
@mksprite
def null(screen,x,y,s,t):
pygame.draw.rect(screen, (90,90,90), (x,y,s,s))
@mkshot
def null(*args): pass
@mksprite
def cannon(screen,x,y,s,t):
pygame.draw.rect(screen, (90+165*(t.elem==0),90+165*(t.elem==1),90+165*(t.elem==2)), (x,y,s,s))
pygame.draw.line(screen, (255,0,0), (x+s/2,y+s/2),(t.tx,t.ty))
@mkshot
def cannon(*args): pass

12
utils.py Normal file
View File

@ -0,0 +1,12 @@
import math
# DIRECTIONS GO BACKWARDS IN THIS GAME
# WHY NOT
def get_direction(x1,y1,x2,y2):
dx,dy=x2-x1,y2-y1
if dx==0: return math.pi*(2-sign(dy))/2
t=math.atan(dy/dx)
return t+math.pi*(sign(dx)<0)
def sign(num):
return (num>=0)*2-1-(num==0)

28
workers.py Normal file
View File

@ -0,0 +1,28 @@
import pygame
import enum
import math
import random
import utils
behaviours=enum.Enum('behaviours',['Cursor','Average'])
class Worker():
def __init__(self,x,y,behaviour,grid):
self.x,self.y,self.behaviour,self.grid=x,y,behaviour,grid
self.direction=0
def target(self):
if self.behaviour==behaviours.Cursor:
return pygame.mouse.get_pos()
if self.behaviour==behaviours.Average:
return self.grid.mx,self.grid.my
def draw(self,screen):
pygame.draw.circle(screen,'grey',(self.x,self.y),8)
pygame.draw.circle(screen,'black',(self.x+math.cos(self.dir)*5,self.y+math.sin(self.dir)*5),3)
def update(self,events):
mx,my=self.target()
self.dir=utils.get_direction(self.x,self.y,mx,my)
speed=min(5,((mx-self.x)**2+(my-self.y)**2)**0.5*0.1)
self.x+=math.cos(self.dir)*speed
self.y+=math.sin(self.dir)*speed