summaryrefslogtreecommitdiff
path: root/bubbob/ext1/__init__.py
diff options
context:
space:
mode:
Diffstat (limited to 'bubbob/ext1/__init__.py')
-rw-r--r--bubbob/ext1/__init__.py403
1 files changed, 403 insertions, 0 deletions
diff --git a/bubbob/ext1/__init__.py b/bubbob/ext1/__init__.py
new file mode 100644
index 0000000..9f90b0c
--- /dev/null
+++ b/bubbob/ext1/__init__.py
@@ -0,0 +1,403 @@
+from __future__ import generators
+import os, math, random
+import images, gamesrv
+from images import ActiveSprite
+from boards import CELL, HALFCELL
+from mnstrmap import GreenAndBlue
+from bubbles import BubblingEyes, Bubble
+from bonuses import Bonus
+
+LocalDir = os.path.basename(os.path.dirname(__file__))
+
+
+localmap = {
+ 'ark-paddle': ('image1-%d.ppm', (0, 0, 80, 32)),
+ }
+
+music = gamesrv.getmusic(os.path.join(LocalDir, 'music.wav'))
+snd_wall = gamesrv.getsample(os.path.join(LocalDir, 'wall.wav'))
+snd_brick = gamesrv.getsample(os.path.join(LocalDir, 'brick.wav'))
+
+
+def aget(x, y):
+ if 0 <= x < curboard.width and y >= 0:
+ if y >= curboard.height:
+ return ' '
+ return curboard.walls[y][x]
+ else:
+ return '#'
+
+def sign(x):
+ if x >= 0.0:
+ return 1
+ else:
+ return -1
+
+
+class PaddleEyes(BubblingEyes):
+
+ def __init__(self, bubber, saved_caps, paddle):
+ BubblingEyes.__init__(self, bubber, saved_caps, paddle)
+ self.deltax = (paddle.ico.w - self.ico.w) // 2
+ self.deltay = (paddle.ico.h - self.ico.h) // 2
+ self.step(self.deltax, self.deltay)
+
+ def playing_bubble(self, paddle, accel=0.75, vmax=4.5):
+ import boards
+ dx = self.deltax
+ dy = self.deltay
+ bubber = paddle.bubber
+ vx = 0.0
+ fx = paddle.x
+ while paddle.alive:
+ wannago = bubber.wannago(self.dcap)
+ if paddle.timeleft is None:
+ keydy = 0
+ else:
+ keydy = -1
+ key = ('eyes', wannago, keydy)
+ if fx < 2*CELL:
+ if vx < 0.0:
+ vx = -vx * 0.45
+ wannago = 1
+ elif fx + paddle.ico.w > boards.bwidth - 2*CELL:
+ if vx > 0.0:
+ vx = -vx * 0.45
+ wannago = -1
+ if not wannago:
+ if -accel <= vx <= accel:
+ vx = 0
+ elif vx < 0.0:
+ wannago = 0.7
+ else:
+ wannago = -0.7
+ vx += accel * wannago
+ if vx < -vmax:
+ vx = -vmax
+ elif vx > vmax:
+ vx = vmax
+ fx += vx
+ paddle.move(int(fx), paddle.y)
+ self.move(paddle.x+dx, paddle.y+dy, images.sprget(key))
+ yield None
+ self.kill()
+
+ def bottom_up(self):
+ return 0
+
+
+class Paddle(ActiveSprite):
+
+ def __init__(self, arkanoid, bubber, px, py):
+ ico = images.sprget(('ark-paddle', bubber.pn))
+ ActiveSprite.__init__(self, ico, px - (ico.w-2*CELL)//2,
+ py - (ico.h-2*CELL)//2)
+ self.arkanoid = arkanoid
+ self.bubber = bubber
+ self.timeleft = None
+ self.gen.append(self.bounce_down())
+ self.gen.append(self.bkgndstuff())
+ self.arkanoid.paddles.append(self)
+
+ def bounce_down(self):
+ import boards
+ target_y = boards.bheight - self.ico.h
+ fy = self.y
+ vy = 0.0
+ while fy < target_y or abs(vy) > 0.3:
+ if fy < target_y:
+ vy += 0.3
+ elif vy > 0.0:
+ vy = -vy / 3.0
+ fy += vy
+ self.move(self.x, int(fy))
+ yield None
+ while self.y > target_y:
+ self.step(0, -2)
+ yield None
+ self.move(self.x, target_y)
+ self.gen.append(self.wait_and_shoot())
+
+ def wait_and_shoot(self):
+ timeout = 30
+ while timeout > 0:
+ timeout -= self.arkanoid.ready
+ yield None
+ self.gen.append(self.catch(Ball(self)))
+
+ def catch(self, ball):
+ import boards
+ while ball.alive:
+ if ball.y > boards.bheight//2+1 and ball.vy > 0.0:
+ deltay = self.y - Ball.Y_MARGIN - ball.y
+ self.timeleft = deltay / ball.vy
+ #if -1.25 <= self.timeleft <= 0.5:
+ if -12 <= deltay <= 1:
+ ball.bouncepad(self.arkanoid.paddles)
+ yield None
+ self.timeleft = None
+ if ball.missed:
+ self.kill()
+
+ def kill(self):
+ 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.arkanoid.paddles.remove(self)
+ except ValueError:
+ pass
+ ActiveSprite.kill(self)
+
+ def bkgndstuff(self):
+ while 1:
+ if self.timeleft is not None:
+ self.arkanoid.order.append((self.timeleft, self))
+ yield None
+ touching = images.touching(self.x+1, self.y+1,
+ self.ico.w-2, self.ico.h-2)
+ touching.reverse()
+ for s in touching:
+ if isinstance(s, Bonus):
+ s.touched(self)
+
+ def score(self, hits):
+ bricks = self.arkanoid.bricks
+ bricks[self.bubber] = bricks.get(self.bubber, 0) + hits
+ self.bubber.givepoints(125*(2**hits))
+
+
+class Ball(ActiveSprite):
+
+ Y_MARGIN = 20
+ SPEED = 5.8
+
+ def __init__(self, paddle):
+ self.paddle = paddle
+ imglist1 = GreenAndBlue.new_bubbles[paddle.bubber.pn]
+ ActiveSprite.__init__(self, images.sprget(imglist1[0]),
+ paddle.x + paddle.ico.w//2,
+ paddle.y - Ball.Y_MARGIN)
+ self.missed = 0
+ self.setimages(self.imgseq(imglist1[1:], 6))
+ self.bounceangle(0.2)
+ self.gen.append(self.flying())
+
+ def bouncepad(self, paddles):
+ for paddle in paddles:
+ dx = (self.x + self.ico.w//2) - (paddle.x + paddle.ico.w//2)
+ dxmax = paddle.ico.w//2
+ angle = float(dx) / dxmax
+ if 0.0 <= angle <= 1.0:
+ angle = angle * 1.111 + 0.07
+ elif -1.0 <= angle <= 0.0:
+ angle = angle * 1.111 - 0.07
+ else:
+ continue
+ self.bounceangle(angle)
+ self.play(snd_wall)
+ break
+
+ def bounceangle(self, angle):
+ self.vx = math.sin(angle) * self.SPEED
+ self.vy = - math.cos(angle) * self.SPEED
+
+ def flying(self):
+ import boards
+ fx = self.x
+ fy = self.y
+ while self.y < boards.bheight:
+ fx += self.vx
+ fy += self.vy
+ self.move(int(fx), int(fy))
+ yield None
+ cx = self.x // CELL + 1
+ cy = self.y // CELL + 1
+ dx = sign(self.vx)
+ dy = sign(self.vy)
+ hits = 0.0
+ if aget(cx, cy) == '#':
+ hits += self.ahit(cx, cy, 0, 0)
+ if aget(cx+dx, cy) == '#':
+ hits += self.ahit(cx+dx, cy, 0, dy)
+ self.vx = -self.vx
+ if aget(cx, cy+dy) == '#':
+ hits += self.ahit(cx, cy+dy, dx, 0)
+ self.vy = -self.vy
+ if hits:
+ hits = int(hits)
+ if hits:
+ self.paddle.score(hits)
+ self.play(snd_brick)
+ else:
+ self.play(snd_wall)
+ self.missed = 1
+ self.kill()
+
+ def ahit(self, cx, cy, dx, dy):
+ total = 0.01
+ for i in (-1, 0, 1):
+ x = cx + i*dx
+ y = cy + i*dy
+ if (2 <= x < curboard.width - 2 and 0 <= y < curboard.height and
+ aget(x, y) == '#'):
+ curboard.killwall(x, y)
+ self.paddle.arkanoid.killedbricks += 1
+ total += 1.0
+ return total
+
+ def pop(self):
+ self.play(images.Snd.Pop)
+ self.gen = [self.die(Bubble.exploding_bubbles)]
+
+
+class Arkanoid:
+
+ def bgen(self, limittime = 60.1): # 0:60
+ import boards
+ from player import BubPlayer
+
+ self.bricks = {}
+ for t in boards.initsubgame(music, self.displaypoints):
+ yield t
+
+ tc = boards.TimeCounter(limittime)
+ self.ready = 0
+ self.builddelay = {}
+ self.nbbricks = 0
+ self.order = []
+ self.paddles = []
+ #finish = 0
+ for t in self.frame():
+ self.order_paddles()
+ t = boards.normal_frame()
+ self.build_paddles()
+ yield t
+ #if len(self.paddles) == 0:
+ # finish += 1
+ # if finish == 20:
+ # break
+ #else:
+ # finish = 0
+ tc.update(t)
+ if tc.time == 0.0:
+ break
+ if (BubPlayer.FrameCounter & 15) == 7:
+ for s in images.ActiveSprites:
+ if isinstance(s, Bonus):
+ s.timeout = 0 # bonuses stay
+ elif isinstance(s, Bubble):
+ s.pop()
+
+ tc.restore()
+ self.ready = 0
+ for s in images.ActiveSprites[:]:
+ if isinstance(s, Ball):
+ s.pop()
+ for t in boards.result_ranking(self.bricks, self.nbbricks):
+ self.build_paddles()
+ yield t
+ self.remove_paddles()
+ self.unframe()
+
+ def displaypoints(self, bubber):
+ return self.bricks.get(bubber, 0)
+
+ def frame(self):
+ for y in range(curboard.height-1, curboard.height//2, -1):
+ yield None
+ yield None
+ for x in range(2, curboard.width-2):
+ if aget(x, y) == '#':
+ curboard.killwall(x, y)
+ brickline = curboard.width-4
+ expected = (brickline * curboard.height) // 5
+ y = curboard.height//2
+ nbbricks = 0
+ while y>=0 and nbbricks + (y+1)*brickline >= expected:
+ yield None
+ for x in range(2, curboard.width-2):
+ if aget(x, y) == '#':
+ nbbricks += 1
+ y -= 1
+ while y >= -1:
+ yield None
+ yield None
+ for x in range(2, curboard.width-2):
+ if y < 0 or aget(x, y) == ' ':
+ curboard.putwall(x, y)
+ nbbricks += brickline
+ curboard.reorder_walls()
+ y -= 1
+
+ nbbricks -= brickline
+ self.ready = 1
+ self.nbbricks = nbbricks
+ self.killedbricks = 0
+ while self.killedbricks < self.nbbricks:
+ yield None
+
+ def unframe(self):
+ for x in range(2, curboard.width-2):
+ curboard.killwall(x, -1)
+
+ def build_paddles(self):
+ from player import BubPlayer
+ for p in BubPlayer.PlayerList:
+ dragons = [d for d in p.dragons if not isinstance(d, PaddleEyes)]
+ if dragons and len(p.dragons) == len(dragons):
+ if self.builddelay.get(p):
+ self.builddelay[p] -= 1
+ else:
+ self.builddelay[p] = 53
+ dragon = random.choice(dragons)
+ paddle = Paddle(self, p, dragon.x, dragon.y)
+ eyes = PaddleEyes(p, dragon.dcap, paddle)
+ p.dragons.append(eyes)
+ p.emotic(dragon, 4)
+ for d in dragons:
+ d.kill()
+
+ def order_paddles(self):
+ self.order.sort()
+ self.order.reverse()
+ for timeleft, paddle in self.order:
+ try:
+ self.paddles.remove(paddle)
+ except ValueError:
+ pass
+ else:
+ self.paddles.insert(0, paddle)
+ paddle.to_front()
+ del self.order[:]
+
+ def remove_paddles(self):
+ killclasses = (Paddle, PaddleEyes, Ball, Bonus)
+ for s in images.ActiveSprites[:]:
+ if isinstance(s, killclasses):
+ s.kill()
+
+# This game is suitable for at least min_players players
+min_players = 1
+
+def run():
+ global curboard
+ import boards
+ from boards import curboard
+ boards.replace_boardgen(Arkanoid().bgen())
+
+def setup():
+ from player import BubPlayer
+ for key, (filename, rect) in 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()