nbsdgames/bubbob/ext3/__init__.py
2022-02-03 13:46:22 +03:30

368 lines
12 KiB
Python

import os, math, random
import images, gamesrv
from images import ActiveSprite
import boards
from boards import CELL, HALFCELL, bget
from mnstrmap import GreenAndBlue, Fire
from bonuses import Bonus
from player import Dragon, BubPlayer
import monsters
from bubbles import Bubble
LocalDir = os.path.basename(os.path.dirname(__file__))
localmap = {
'gala': ('image1-%d.ppm', (0, 0, 32, 32)),
}
music = gamesrv.getmusic(os.path.join(LocalDir, 'music.wav'))
snd_shoot = gamesrv.getsample(os.path.join(LocalDir, 'shoot.wav'))
class Ship(ActiveSprite):
def __init__(self, galaga, bubber, x, y):
ico = images.sprget(('gala', bubber.pn))
ActiveSprite.__init__(self, ico, x, y)
self.galaga = galaga
self.bubber = bubber
self.gen.append(self.movedown())
self.gen.append(self.playing_ship())
self.gen.append(self.doomed())
self.galaga.ships.append(self)
def movedown(self):
import boards
target_y = boards.bheight - self.ico.h
while self.y < target_y:
yield None
self.move(self.x, self.y + 3)
self.move(self.x, target_y)
def playing_ship(self):
import boards
bubber = self.bubber
xmin = HALFCELL
xmax = boards.bwidth - HALFCELL - self.ico.w
fire = 0
while 1:
wannago = bubber.wannago(self.dcap)
nx = self.x + 2*wannago
if nx < xmin:
nx = xmin
elif nx > xmax:
nx = xmax
self.move(nx, self.y)
if fire:
fire -= 1
elif bubber.key_fire:
self.firenow()
fire = 28
yield None
def firenow(self):
ico = images.sprget(GreenAndBlue.new_bubbles[self.bubber.pn][0])
s = Shot(ico, self.x, self.y)
s.d = self
s.gen = [s.straightup(self)]
self.play(snd_shoot)
def doomed(self):
dangerous = Alien, monsters.MonsterShot
while 1:
touching = images.touching(self.x+3, self.y+3, 26, 26)
for s in touching:
if isinstance(s, dangerous):
self.kill()
return
yield None
yield None
def kill(self):
try:
self.bubber.dragons.remove(self)
except ValueError:
pass
images.Snd.Pop.play(1.0, pad=0.0)
images.Snd.Pop.play(1.0, pad=1.0)
ico = images.sprget(Bubble.exploding_bubbles[0])
for i in range(11):
s = ActiveSprite(ico,
self.x + random.randrange(self.ico.w) - CELL,
self.y + random.randrange(self.ico.h) - CELL)
s.gen.append(s.die(Bubble.exploding_bubbles))
try:
self.galaga.ships.remove(self)
except ValueError:
pass
ActiveSprite.kill(self)
class Shot(Bubble):
touchable = 0
def straightup(self, ship):
ymin = -self.ico.h
while self.y > ymin:
self.step(0, -10)
touching = images.touching(self.x+CELL-1, self.y+CELL-1, 2, 2)
touching = [s for s in touching if isinstance(s, Alien)]
if touching:
alien = random.choice(touching)
self.gen = []
self.touchable = 1
self.move(alien.x, alien.y)
self.pop([ship])
alien.kill()
scores = ship.galaga.scores
scores[ship.bubber] = scores.get(ship.bubber, 0) + 1
ship.bubber.givepoints(100)
return
yield None
def popped(self, dragon):
return 200
class Alien(monsters.Monster):
ANGLES = 32
SPEED = 5
ANGLE_TABLE = [(SPEED * math.cos(a*2.0*math.pi/ANGLES),
-SPEED * math.sin(a*2.0*math.pi/ANGLES))
for a in range(ANGLES)]
touchable = 0
def __init__(self, galaga, squadron, rank, relativey):
centerx = boards.bwidth // 2
go_left = squadron % 2
dx = (1,-1)[go_left]
halfspan = centerx*7//12
relativex = - halfspan + 4*CELL*rank
if relativex > halfspan:
raise StopIteration
if squadron % 3 == 2:
from mnstrmap import Ghosty as mcls
else:
from mnstrmap import Flappy as mcls
mdef = mcls(centerx // CELL - 1, -7, go_left)
mdef.left_weapon = mdef.right_weapon = [Fire.drop]
monsters.Monster.__init__(self, mdef)
self.path = [(None, centerx + (dx*centerx)*2//3, boards.bheight//3),
(None, centerx - (dx*centerx)*4//5, boards.bheight//6),
(galaga, -dx*relativex, -relativey)]
self.gen = [self.waiting(rank * 20)]
self.in_place = 0
galaga.nbmonsters += 1
def default_mode(self, angle=ANGLES//4):
self.touchable = 1
speed = self.SPEED
relative, tx, ty = self.path[0]
fx = self.x
fy = self.y
ymax = boards.bheight - self.ico.h
cont = 1
if relative:
shoot_prob = 0.0085
else:
shoot_prob = 0.021
while cont:
if self.angry:
self.kill() # never getting out of a bubble
return
if relative:
dx = relative.globalx + tx
dy = relative.globaly + ty
else:
dx = tx
dy = ty
dx -= self.x
dy -= self.y
tests = []
for a1 in (-1, 0, 1):
a1 = (angle+a1) % self.ANGLES
testx, testy = self.ANGLE_TABLE[a1]
testx -= dx
testy -= dy
tests.append((testx*testx+testy*testy, a1))
ignored, angle = min(tests)
if dx*dx+dy*dy > speed*speed:
dx, dy = self.ANGLE_TABLE[angle]
elif relative:
self.in_place = 1
if self.y > ymax and relative.ships:
for ship in relative.ships[:]:
ship.kill()
relative.builddelay[ship.bubber] = 9999
relative.gameover = 1
#x0 = self.x//CELL + 1
#if x0 < 2: x0 = 0
#if x0 >= boards.width-2: x0 = boards.width-3
#bubbles.FireFlame(x0, boards.height-2, None, [-1, 1],
# boards.width)
else:
self.path.pop(0)
self.gen.append(self.default_mode(angle))
cont = 0
fx += dx
fy += dy
self.move(int(fx), int(fy))
if dx and (self.dir > 0) != (dx > 0):
self.dir = -self.dir
self.resetimages()
if random.random() < shoot_prob and self.y >= 0:
monsters.DownShot(self)
yield None
class Galaga:
gameover = 0
def bgen(self):
self.scores = {}
for t in boards.initsubgame(music, self.displaypoints):
yield t
self.ships = []
self.builddelay = {}
self.nbmonsters = 0
#finish = 0
for t in self.frame():
t = boards.normal_frame()
self.build_ships()
yield t
#if len(self.ships) == 0:
# finish += 1
# if finish == 50:
# break
#else:
# finish = 0
if (BubPlayer.FrameCounter & 15) == 7:
for s in images.ActiveSprites:
if isinstance(s, Bubble) and not isinstance(s, Shot):
s.pop()
for t in boards.result_ranking(self.scores, self.nbmonsters):
self.build_ships()
yield t
for s in images.ActiveSprites[:]:
if isinstance(s, (Alien, Ship)):
s.kill()
def displaypoints(self, bubber):
return self.scores.get(bubber, 0)
def frame(self):
curboard.walls_by_pos.clear()
curboard.winds = ['v' * curboard.width] * curboard.height
for y in range(len(curboard.walls)):
curboard.walls[y] = ' ' * len(curboard.walls[y])
l1 = curboard.sprites['walls']
l2 = curboard.sprites['borderwalls']
while l1 or l2:
for l in [l1, l2]:
for w in l[:]:
w.step(0, 5)
if w.y >= boards.bheight:
l.remove(w)
w.kill()
yield None
self.globalx = boards.bwidth // 2
self.globaly = 0
shifter = self.shifter()
squadrons = len([p for p in BubPlayer.PlayerList if p.isplaying()])
squadrons = 3 + (squadrons+1)//3
nextsquad = 0
relativey = 0
squadtime = 0
while not self.gameover:
yield None
#if random.random() < 0.015:
# bubbles.sendbubble(bubbles.PlainBubble, top=0)
in_place = {0: [], 1: [], 2: []}
for s in BubPlayer.MonsterList:
if isinstance(s, Alien):
in_place[s.in_place].append(s)
toohigh = self.globaly - relativey < -3*CELL
if in_place[1]:
xbounds = [s.x for s in in_place[1]]
self.alien_bounds = min(xbounds), max(xbounds)
next(shifter)
elif toohigh:
self.globaly += 1
squadtime -= 1
if nextsquad >= squadrons:
if not (in_place[0] or in_place[1]):
break
elif squadtime < 0 and not toohigh:
squadtime = 200
try:
rank = 0
while 1:
Alien(self, nextsquad, rank, relativey)
rank += 1
except StopIteration:
pass
nextsquad += 1
relativey += 4*CELL
for t in range(20):
yield None
def shifter(self):
while 1:
# go right
while self.alien_bounds[1] < boards.bwidth-5*CELL:
self.globalx += 2
yield None
# go down
for i in range(3*CELL):
self.globaly += 1
yield None
# go left
while self.alien_bounds[0] > 3*CELL:
self.globalx -= 2
yield None
# go down
for i in range(3*CELL):
self.globaly += 1
yield None
def build_ships(self):
for p in BubPlayer.PlayerList:
dragons = [d for d in p.dragons if not isinstance(d, Ship)]
if dragons and len(p.dragons) == len(dragons):
if self.builddelay.get(p):
self.builddelay[p] -= 1
else:
self.builddelay[p] = 75
dragon = random.choice(dragons)
ship = Ship(self, p, dragon.x, dragon.y)
ship.dcap = dragon.dcap
p.dragons.append(ship)
p.emotic(dragon, 4)
for d in dragons:
d.kill()
# This game is suitable for at least min_players players
min_players = 1
def run():
global curboard
from boards import curboard
boards.replace_boardgen(Galaga().bgen())
def setup():
for key, (filename, rect) in list(localmap.items()):
filename = os.path.join(LocalDir, filename)
if filename.find('%d') >= 0:
for p in BubPlayer.PlayerList:
images.sprmap[key, p.pn] = (filename % p.pn, rect)
else:
images.sprmap[key] = (filename, rect)
setup()