There are a lot of fish in this pond, and you’re the tiniest. Avoid the bigger fish and eat smaller or same-sized fish to get bigger, so you can become the Top Fish!
You might recognize this game from a lot of places, I’m pretty sure there are tons of clones of this type of game. I wanted to add a few more things, like sound effects, but ran out of time.
Download:
topfish.bin (148.0 KB)
topfish.zip (11.5 KB) (source)
Or check out the source here:
main.py
# Top Fish by wuuff
# Code and Graphics License: CC0
import upygame as pygame
import umachine as pok
import urandom as random
pygame.display.init()
screen = pygame.display.set_mode() # full screen
screenRect = screen.get_rect()
screenW = screenRect.width
screenH = screenRect.height
level = 0
state_game = 0
state_dead = 1
state_win = 2
state = state_game
state_timer = 0
pygame.display.set_palette_16bit([
0x0536, 0x0126, 0x03b9, 0xd7bf, 0xf701, 0xdea9, 0xf360, 0xdb81, 0xc800, 0x8806, 0x032a, 0x4448, 0x7015, 0x7296, 0x8e2e, 0xd636
])
tinyFishPixels = b'\
\x40\x40\
\x04\x14\
\x40\x40\
'
tinyFishPixelsL = b'\
\x04\x04\
\x41\x40\
\x04\x04\
'
teenyFishPixels = b'\
\x60\x60\
\x66\x16\
\x06\x66\
\x60\x60\
'
teenyFishPixelsL = b'\
\x06\x06\
\x61\x66\
\x66\x60\
\x06\x06\
'
smallFishPixels = b'\
\x89\x99\x80\
\x08\x88\x18\
\x08\x88\x88\
\x88\x99\x80\
'
smallFishPixelsL = b'\
\x08\x99\x98\
\x81\x88\x80\
\x88\x88\x80\
\x08\x99\x88\
'
medFishPixels = b'\
\xab\xaa\xbb\xa0\
\x0b\xbb\xba\x1a\
\x0b\xbb\xba\xaa\
\xab\xba\xab\xa0\
'
medFishPixelsL = b'\
\x0a\xbb\xaa\xba\
\xa1\xab\xbb\xb0\
\xaa\xbb\xbb\xb0\
\x0a\xba\xab\xba\
'
largeFishPixels = b'\
\xdd\xd0\xdc\xcd\xd0\
\x00\xdd\xcc\xcc\x1c\
\x0d\xdc\xcc\xdc\x1c\
\xdd\x0c\xdd\xdc\xcc\
'
largeFishPixelsL = b'\
\x0d\xdc\xcd\x0d\xdd\
\xc1\xcc\xcc\xdd\x00\
\xc1\xcd\xcc\xcd\xd0\
\xcc\xcd\xdd\xc0\xdd\
'
hugeFishPixels = b'\
\xc2\x20\xc2\x2c\x22\x20\
\x0c\x22\x2c\x22\x11\x12\
\x00\xcc\x2c\x22\xc1\x22\
\x0c\x22\x2c\x22\xc2\x22\
\xc2\x20\xc2\x2c\x22\x20\
'
hugeFishPixelsL = b'\
\x02\x22\xc2\x2c\x02\x2c\
\x21\x11\x22\xc2\x22\xc0\
\x22\x1c\x22\xc2\xcc\x00\
\x22\x2c\x22\xc2\x22\xc0\
\x02\x22\xc2\x2c\x02\x2c\
'
gargantuanFishPixels = b'\
\xcc\x0c\xcc\xcc\xdd\xdd\xd0\
\x0c\xc0\xdd\xdd\xdd\x11\xdd\
\x05\x55\x55\x55\x55\x11\x55\
\x09\x99\x99\x99\x99\x11\x99\
\x0c\xc0\xdd\xdd\xdd\xdd\xdd\
\xcc\x0c\xcc\xcd\xdd\xdd\xd0\
'
gargantuanFishPixelsL = b'\
\x0d\xdd\xdd\xcc\xcc\xc0\xcc\
\xdd\x11\xdd\xdd\xdd\x0c\xc0\
\x55\x11\x55\x55\x55\x55\x50\
\x99\x11\x99\x99\x99\x99\x90\
\xdd\xdd\xdd\xdd\xdd\x0c\xc0\
\x0d\xdd\xdd\xdc\xcc\xc0\xcc\
'
wowFishPixels = b'\
\x66\x60\x66\x66\x76\x66\x77\x00\
\x06\x66\x07\x77\x77\x79\x97\x70\
\x00\x67\x67\x66\x67\x77\x19\x77\
\x00\x06\x76\x66\x67\x77\x17\x77\
\x00\x67\x67\x66\x67\x77\x77\x77\
\x06\x66\x07\x77\x77\x77\x77\x70\
\x66\x60\x66\x67\x77\x66\x67\x00\
'
wowFishPixelsL = b'\
\x00\x77\x66\x67\x66\x66\x06\x66\
\x07\x79\x97\x77\x77\x70\x66\x60\
\x77\x91\x77\x76\x66\x76\x76\x00\
\x77\x71\x77\x76\x66\x67\x60\x00\
\x77\x77\x77\x76\x66\x76\x76\x00\
\x07\x77\x77\x77\x77\x70\x66\x60\
\x00\x76\x66\x77\x76\x66\x06\x66\
'
seaweedPixels = b'\
\x00\x00\xe0\x00\
\x00\x0e\x00\x00\
\x00\x00\xe0\x00\
\x00\x0e\x00\x00\
\x00\x00\xe0\x00\
\x00\x0e\xe0\x00\
\x0f\xff\xff\xf0\
\xff\xff\xff\xff\
'
seaweedPixels2 = b'\
\x00\x0e\x00\x00\
\x00\x00\xe0\x00\
\x00\x0e\x00\x00\
\x00\x00\xe0\x00\
\x00\x0e\x00\x00\
\x00\x0e\xe0\x00\
\x0f\xff\xff\xf0\
\xff\xff\xff\xff\
'
sandPixels = b'\
\x00\x00\x00\x00\
\x00\x00\x00\x00\
\x00\x00\x00\x00\
\x00\x00\x00\x00\
\x00\x00\x00\x00\
\x00\x00\x00\x00\
\x00\xff\xff\x00\
\xff\xff\xff\xff\
'
tinyFishSurf = pygame.surface.Surface(4,3,tinyFishPixels)
tinyFishSurfL = pygame.surface.Surface(4,3,tinyFishPixelsL)
teenyFishSurf = pygame.surface.Surface(4,4,teenyFishPixels)
teenyFishSurfL = pygame.surface.Surface(4,4,teenyFishPixelsL)
smallFishSurf = pygame.surface.Surface(6,4,smallFishPixels)
smallFishSurfL = pygame.surface.Surface(6,4,smallFishPixelsL)
medFishSurf = pygame.surface.Surface(8,4,medFishPixels)
medFishSurfL = pygame.surface.Surface(8,4,medFishPixelsL)
largeFishSurf = pygame.surface.Surface(10,4,largeFishPixels)
largeFishSurfL = pygame.surface.Surface(10,4,largeFishPixelsL)
hugeFishSurf = pygame.surface.Surface(12,5,hugeFishPixels)
hugeFishSurfL = pygame.surface.Surface(12,5,hugeFishPixelsL)
gargantuanFishSurf = pygame.surface.Surface(14,6,gargantuanFishPixels)
gargantuanFishSurfL = pygame.surface.Surface(14,6,gargantuanFishPixelsL)
wowFishSurf = pygame.surface.Surface(16,7,wowFishPixels)
wowFishSurfL = pygame.surface.Surface(16,7,wowFishPixelsL)
sandSurf = pygame.surface.Surface(8,8,sandPixels)
weedSurf = pygame.surface.Surface(8,8,seaweedPixels)
weedSurf2 = pygame.surface.Surface(8,8,seaweedPixels2)
class Fish:
def __init__(self, drawable, drawableL, width, height, rank):
self.drawable = drawable
self.drawableL = drawableL
self.width = width
self.height = height
self.rank = rank
fishes = [Fish(tinyFishSurf,tinyFishSurfL,4,3,0),Fish(teenyFishSurf,teenyFishSurfL,4,4,1),Fish(smallFishSurf,smallFishSurfL,6,4,2),Fish(medFishSurf,medFishSurfL,8,4,3),
Fish(largeFishSurf,largeFishSurfL,10,4,4),Fish(hugeFishSurf,hugeFishSurfL,12,5,5),Fish(gargantuanFishSurf,gargantuanFishSurfL,14,6,6),Fish(wowFishSurf,wowFishSurfL,16,7,7)]
vmax = 64
class Entity:
def step(self):
if self.vx > vmax:
self.vx = vmax
if self.vx < -vmax:
self.vx = -vmax
if self.vy > vmax:
self.vy = vmax
if self.vy < -vmax:
self.vy = -vmax
self.x += self.vx
self.y += self.vy
self.rect.x = self.x
self.rect.y = self.y
def draw(self):
if self.dir == 0:
screen.blit( self.fish.drawable, self.x//8, self.y//8, 0 )
else:
screen.blit( self.fish.drawableL, self.x//8, self.y//8, 0 )
def __init__(self, x, y, fish):
self.x = x
self.y = y
self.vx = 0
self.vy = 0
self.dir = 0
self.fish = fish
self.rect = pygame.Rect(x,y,fish.width*8,fish.height*8)
class Player(Entity):
def die(self):
global state
global state_timer
global level
state = state_dead
state_timer = 0
level = 0
if self.score > self.hiscore:
self.hiscore = self.score
self.fish = fishes[0]
self.rect.width = self.fish.width*8
self.rect.height = self.fish.height*8
self.x = screenW//2*8
self.y = screenH//2*8
self.vx = 0
self.vy = 0
self.rscore = 0
self.score = 0
def win(self):
global state
global state_timer
global level
state = state_win
state_timer = 0
level += 1
self.fish = fishes[0]
self.rect.width = self.fish.width*8
self.rect.height = self.fish.height*8
self.x = screenW//2*8
self.y = screenH//2*8
self.vx = 0
self.vy = 0
self.rscore = 0
def step(self):
if self.vx > 0:
self.dir = 0
elif self.vx < 0:
self.dir = 1
if keys[pygame.K_LEFT]:
if self.vx > 0:
self.vx -= 4
else:
self.vx -= 2
if keys[pygame.K_RIGHT]:
if self.vx < 0:
self.vx += 4
else:
self.vx += 2
if keys[pygame.K_UP]:
if self.vy > 0:
self.vy -= 4
else:
self.vy -= 2
if keys[pygame.K_DOWN]:
if self.vy < 0:
self.vy += 4
else:
self.vy += 2
super().step()
for entity in entities:
if isinstance(entity, Enemy):
if self.rect.colliderect(entity.rect):
if self.fish.rank >= entity.fish.rank:
self.rscore += entity.fish.rank+1
self.score += entity.fish.rank+1
if self.rscore > (self.fish.rank+1)*2:
# Rank up or win
if self.fish.rank < len(fishes)-1:
self.fish = fishes[self.fish.rank+1]
self.rect.width = self.fish.width*8
self.rect.height = self.fish.height*8
self.rscore = 0
else:
self.win()
entity.spawn()
else:
self.die()
pok.draw_text(0,0,"HIT", 1)
# Friction
if self.vx > 0:
self.vx -= 1
self.dir = 0
if self.vx < 0:
self.vx += 1
self.dir = 1
if self.vy > 0:
self.vy -= 1
if self.vy < 0:
self.vy += 1
# Borders
if self.x > screenW*8-self.fish.width*8:
self.x = screenW*8-self.fish.width*8
if self.x < 0:
self.x = 0
if self.y > screenH*8-self.fish.width*8:
self.y = screenH*8-self.fish.width*8
if self.y < 0:
self.y = 0
def draw(self):
super().draw()
pok.draw_text(0,0,'%d'%self.score,1)
pok.draw_text(screenW-4*5,0,'%-4d'%self.hiscore,1)
def __init__(self,x,y,fish):
super().__init__(x,y,fish)
self.score = 0
self.rscore = 0
self.hiscore = 0
class Enemy(Entity):
def step(self):
super().step()
if self.x < -8*8 or self.x > (screenW+8)*8:
self.spawn()
def spawn(self):
self.fish = fishes[random.getrandbits(3)]
self.x = -self.fish.width*8
self.dir = 0
self.rect.width = self.fish.width*8
self.rect.height = self.fish.height*8
#self.y = (10*random.getrandbits(3))*8
self.vx = 1+level*4+random.getrandbits(3)
if random.getrandbits(1) == 0:
self.dir = 1
self.vx *= -1
self.x = (screenW+8)*8
def __init__(self, x, y):
super().__init__(x, y, fishes[0])
self.spawn()
entities = []
entities.append(Player(screenW//2*8,screenH//2*8,fishes[0]))
entities.append(Enemy(0,10*8))
entities.append(Enemy(0,20*8))
entities.append(Enemy(0,30*8))
entities.append(Enemy(0,40*8))
entities.append(Enemy(0,50*8))
entities.append(Enemy(0,60*8))
entities.append(Enemy(0,70*8))
entities.append(Enemy(0,80*8))
keys = {pygame.K_UP:False,pygame.K_DOWN:False,pygame.K_LEFT:False,pygame.K_RIGHT:False}
timer = 0
frame = False
while True:
timer += 1
if timer%32 == 0:
frame = not frame
e = pygame.event.poll()
if e != pygame.NOEVENT:
if e.type == pygame.KEYDOWN:
keys[e.key] = True
if e.type == pygame.KEYUP:
keys[e.key] = False
if state == state_game:
for entity in entities:
entity.step()
entity.draw()
elif state == state_dead or state == state_win:
for entity in entities:
if isinstance(entity,Enemy):
entity.draw()
if state == state_dead:
pok.draw_text(screenW//4,screenH//2,'GAME OVER',1)
else:
pok.draw_text(screenW//4,screenH//2,'TOP FISH!',1)
state_timer += 1
if state_timer > 40:
state = state_game
for entity in entities:
if isinstance(entity,Enemy):
entity.spawn()
for i in range(14):
if i%2 == 0:
if frame:
screen.blit( weedSurf, i*8, screenH-8, 0 )
else:
screen.blit( weedSurf2, i*8, screenH-8, 0 )
else:
screen.blit( sandSurf, i*8, screenH-8, 0 )
pygame.display.flip()