|
from scene import * |
|
import random |
|
from numpy import sign as sgn |
|
score= 0 |
|
chandr=20 |
|
decayRate = 100 # higher is slower |
|
spew = .1 |
|
|
|
leng=-100 |
|
gconst = 1 |
|
rscale = 3 |
|
eggSpeed = 600 |
|
rdeadly = 10 * rscale |
|
cannonForce = - 3 |
|
restart = 0 |
|
eventHorizonCoeff=.5 |
|
|
|
class ChickensInSpace (object): |
|
def __init__(self): |
|
self.arr = [] |
|
self.collision = False |
|
self.m = 0 |
|
def draw(self): |
|
for chicken in self.arr: |
|
chicken.draw() |
|
|
|
def update(self): |
|
index = 0 |
|
for index,chicken in enumerate(self.arr): |
|
if chicken.distance(ship) > rdeadly: |
|
chicken.attract(ship) |
|
if not chicken.isEgg: |
|
for i in range(index+1, len(self.arr)): |
|
try: # poor programming |
|
neighbor = self.arr[i] |
|
except: |
|
continue |
|
#line(chicken.x,chicken.y,neighbor.x,neighbor.y) |
|
if chicken.distance(neighbor) < chicken.r + neighbor.r: |
|
if (not chicken.isEgg and not neighbor.isEgg): |
|
chicken.coalesce(neighbor) |
|
if neighbor.isEgg == chicken.isEgg: |
|
chicken.attract(neighbor) |
|
chicken.update() |
|
|
|
self.getNearest() |
|
|
|
def getNearest(self): |
|
nearest = None |
|
d=999 |
|
for chicken in self.arr: |
|
if chicken.d < d: |
|
d = chicken.d |
|
nearest = chicken |
|
if nearest != None: |
|
r = nearest.r + 5 |
|
# ellipse(nearest.x-r/2,nearest.y-r/2,r,r) |
|
if nearest != None and d<nearest.r+ship.r and nearest.deadly: |
|
self.collision = True |
|
return d |
|
|
|
class Chicken (object): |
|
def __init__(self,x,y,xvel,yvel): |
|
self.isEgg = False |
|
self.x = x |
|
self.y = y |
|
self.m = 1 |
|
self.r = rscale * sqrt(self.m) |
|
self.d = self.distance(ship) |
|
self.xvel = 2*xvel + ship.xvel |
|
self.yvel = 2*yvel + ship.yvel |
|
self.deadly = False |
|
self.blackHole = False |
|
|
|
def distance(self, neighbor): |
|
d = sqrt(pow(self.x - neighbor.x,2) + pow(self.y-neighbor.y,2)) |
|
return d |
|
|
|
|
|
def update(self): |
|
|
|
if self.y + self.yvel > scene.h: |
|
self.yvel = - self.yvel |
|
if self.isEgg: |
|
cis.arr.remove(self) |
|
if self.x + self.xvel > scene.w: |
|
self.xvel = - self.xvel |
|
if self.isEgg: |
|
cis.arr.remove(self) |
|
if self.x + self.xvel < 0: |
|
self.xvel = - self.xvel |
|
if self.isEgg: |
|
try: |
|
cis.arr.remove(self) |
|
except : |
|
pass |
|
if self.y + self.yvel < 0: |
|
self.yvel = - self.yvel |
|
if self.isEgg: |
|
try: |
|
cis.arr.remove(self) |
|
except: |
|
pass |
|
self.x += self.xvel |
|
self.y += self.yvel |
|
if self.blackHole and random.randint(1,decayRate*int(sqrt(self.m))) < sqrt(score/10): |
|
global ship |
|
egg = Chicken(self.x+sgn(ship.x-self.x), self.y+sgn(ship.y-self.y),(ship.x - self.x)/eggSpeed,(ship.y - self.y)/eggSpeed) |
|
egg.isEgg = True |
|
cis.arr.append(egg) |
|
for i in xrange(0,int(score/1000)): |
|
egg=Chicken(self.x+sgn(ship.x-self.x), self.y+sgn(ship.y-self.y),(ship.x - self.x)/eggSpeed + random.uniform(-spew,spew),(ship.y - self.y)/eggSpeed + random.uniform(-spew,spew)) |
|
egg.isEgg = True |
|
cis.arr.append(egg) |
|
self.m-=1 |
|
#for i in xrange(0,sqrt(score/100)): |
|
# egg.isEgg = True |
|
# cis.append(egg) |
|
if self.blackHole: |
|
if self.m > 0 and self.r > rscale *eventHorizonCoeff * sqrt(self.m): |
|
self.r -= .2 # rscale /2 * sqrt(self.m) |
|
if self.m > chandr: |
|
self.blackHole = True |
|
elif self.m < 1: |
|
cis.arr.remove(self) |
|
|
|
self.d = self.distance(ship) |
|
if not self.deadly: |
|
if self.d > rdeadly: |
|
self.deadly = True |
|
|
|
|
|
def coalesce(self,other): |
|
|
|
self.x = (other.x * other.m + self.x * self.m) / (other.m + self.m) |
|
self.y = (other.y * other.m + self.y * self.m) / (other.m + self.m) |
|
self.xvel = (self.m * self.xvel + other.m * other.xvel)/(self.m + other.m) |
|
self.yvel = (other.m * other.yvel)/(self.m + other.m) |
|
self.m += other.m |
|
self.r = rscale * sqrt(self.m) |
|
global cis |
|
if other.blackHole: |
|
self.blackHole = True |
|
if self.blackHole: |
|
self.r = rscale * eventHorizonCoeff * sqrt(self.m) |
|
cis.arr = [ item for item in cis.arr if item != other ] |
|
|
|
def attract(self,neighbor): |
|
d = self.distance(neighbor) |
|
if d>max(neighbor.r,self.r): |
|
self.xvel += gconst * neighbor.m / pow(d,3) * (neighbor.x-self.x) |
|
|
|
self.yvel += gconst * neighbor.m / pow(d,3) * (neighbor.y-self.y) |
|
|
|
neighbor.xvel += gconst * self.m / pow(d,3) * (self.x-neighbor.x) |
|
|
|
neighbor.yvel += gconst * self.m /pow(d,3) * (self.y-neighbor.y) |
|
|
|
def draw(self): |
|
if self.blackHole: |
|
fill(0,0,0) |
|
ellipse(self.x - self.r,self.y-self.r,self.r*2,self.r*2) |
|
ellipse(self.x - 1,self.y-1,2,2) |
|
else: |
|
if self.deadly: |
|
fill(0,1,0) |
|
else: |
|
fill(1,0,0) |
|
if self.isEgg: |
|
fill(1,1,1) |
|
ellipse(self.x - self.r,self.y-self.r,self.r*2,self.r*2) |
|
|
|
class Ship (object): |
|
def __init__(self): |
|
global scene |
|
self.x = scene.w/2 |
|
self.y = scene.h/2 |
|
self.xvel = 0 |
|
self.yvel = 0 |
|
self.m = 3 |
|
self.r = rscale * sqrt(self.m) |
|
|
|
def update(self): |
|
if self.y + self.yvel > scene.h: |
|
self.yvel = - self.yvel |
|
if self.x + self.xvel > scene.w: |
|
self.xvel = - self.xvel |
|
if self.x + self.xvel < 0: |
|
self.xvel = - self.xvel |
|
if self.y + self.yvel < 0: |
|
self.yvel = - self.yvel |
|
self.x += self.xvel |
|
self.y += self.yvel |
|
|
|
def draw(self): |
|
g = gravity() |
|
ellipse(self.x-self.r, self.y-self.r, self.r*2,self.r*2) |
|
|
|
class MyScene (Scene): |
|
|
|
def __init__(self): |
|
self.w=350 |
|
self.h=600 |
|
|
|
def setup(self): |
|
# This will be called before the first frame is drawn. |
|
global ship |
|
ship = Ship() |
|
stroke(0,1,0) |
|
stroke_weight(1) |
|
|
|
pass |
|
|
|
def draw(self): |
|
self.w=self.size.w |
|
self.h=self.size.h |
|
# This will be called for every frame (typically 60 times per second). |
|
background(0, 0, 0) |
|
# Draw a red circle for every finger that touches the screen: |
|
|
|
|
|
global ship |
|
global cis |
|
global restart |
|
if not cis.collision: |
|
g=gravity() |
|
line(ship.x, ship.y, ship.x+leng*g.x,ship.y+leng*g.y) |
|
ship.update() |
|
cis.update() |
|
global score |
|
score += cis.m / 60.0 |
|
if cis.collision and restart is 0: |
|
self.gameOver() |
|
if cis.collision and restart != 0 and self.t > restart: |
|
ship = Ship() |
|
cis = ChickensInSpace() |
|
restart = 0 |
|
global score |
|
score =0 |
|
fill(1,0,1) |
|
ship.draw() |
|
fill(1, 0, 0) |
|
cis.draw() |
|
text(str(int(score)),"helvetica",16,20,20,5) |
|
|
|
def touch_began(self, touch): |
|
c = Chicken(ship.x,ship.y,cannonForce * gravity().x,cannonForce * gravity().y) |
|
ship.xvel -= c.xvel * c.m / ship.m |
|
ship.yvel -= c.yvel * c.m / ship.m |
|
global cis |
|
cis.arr.append(c) |
|
cis.m+=1 |
|
pass |
|
|
|
def touch_moved(self, touch): |
|
pass |
|
|
|
def touch_ended(self, touch): |
|
pass |
|
|
|
def gameOver(self): |
|
global restart |
|
restart = self.t + 3 |
|
|
|
|
|
|
|
scene = MyScene() |
|
cis = ChickensInSpace() |
|
|
|
run(scene) |