mirror of
https://github.com/shlomif/PySolFC.git
synced 2025-04-05 00:02:29 -04:00
+ new animated win
+ animated redeal (old animated win) git-svn-id: file:///home/shlomif/Backup/svn-dumps/PySolFC/svnsync-repos/pysolfc/PySolFC/trunk@129 efabe8c0-fbe8-4139-b769-b5e6d273206e
This commit is contained in:
parent
1e0df4b925
commit
d9bdaa8717
3 changed files with 144 additions and 19 deletions
|
@ -102,6 +102,8 @@ class Options:
|
||||||
self.mahjongg_create_solvable = True
|
self.mahjongg_create_solvable = True
|
||||||
self.shisen_show_hint = True
|
self.shisen_show_hint = True
|
||||||
self.animations = 2 # default to Timer based
|
self.animations = 2 # default to Timer based
|
||||||
|
self.redeal_animation = True
|
||||||
|
self.win_animation = True
|
||||||
self.shadow = True
|
self.shadow = True
|
||||||
self.shade = True
|
self.shade = True
|
||||||
self.shrink_face_down = True
|
self.shrink_face_down = True
|
||||||
|
|
140
pysollib/game.py
140
pysollib/game.py
|
@ -36,6 +36,7 @@
|
||||||
|
|
||||||
# imports
|
# imports
|
||||||
import time
|
import time
|
||||||
|
import math
|
||||||
from cStringIO import StringIO
|
from cStringIO import StringIO
|
||||||
|
|
||||||
# PySol imports
|
# PySol imports
|
||||||
|
@ -374,6 +375,16 @@ class Game:
|
||||||
bookmarks = {},
|
bookmarks = {},
|
||||||
comment = "",
|
comment = "",
|
||||||
)
|
)
|
||||||
|
# some vars for win animation
|
||||||
|
self.win_animation = Struct(
|
||||||
|
timer = None,
|
||||||
|
images = [],
|
||||||
|
tk_images = [], # saved tk images
|
||||||
|
saved_images = {}, # saved resampled images
|
||||||
|
frame_num = 0, # number of the current frame
|
||||||
|
width = 0,
|
||||||
|
height = 0,
|
||||||
|
)
|
||||||
|
|
||||||
def getTitleName(self):
|
def getTitleName(self):
|
||||||
return self.app.getGameTitleName(self.id)
|
return self.app.getGameTitleName(self.id)
|
||||||
|
@ -404,7 +415,9 @@ class Game:
|
||||||
self.finished = False
|
self.finished = False
|
||||||
old_busy, self.busy = self.busy, 1
|
old_busy, self.busy = self.busy, 1
|
||||||
self.setCursor(cursor=CURSOR_WATCH)
|
self.setCursor(cursor=CURSOR_WATCH)
|
||||||
|
self.stopWinAnimation()
|
||||||
self.disableMenus()
|
self.disableMenus()
|
||||||
|
self.redealAnimation()
|
||||||
self.reset(restart=restart)
|
self.reset(restart=restart)
|
||||||
self.resetGame()
|
self.resetGame()
|
||||||
self.createRandom(random)
|
self.createRandom(random)
|
||||||
|
@ -752,6 +765,7 @@ class Game:
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
def _cancelDrag(self, break_pause=True):
|
def _cancelDrag(self, break_pause=True):
|
||||||
|
self.stopWinAnimation()
|
||||||
if self.demo:
|
if self.demo:
|
||||||
self.stopDemo()
|
self.stopDemo()
|
||||||
if break_pause and self.pause:
|
if break_pause and self.pause:
|
||||||
|
@ -772,21 +786,23 @@ class Game:
|
||||||
self.app.menubar.disableMenus()
|
self.app.menubar.disableMenus()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# UI & graphics support
|
# UI & graphics support
|
||||||
#
|
#
|
||||||
|
|
||||||
def _defaultHandler(self):
|
def _defaultHandler(self):
|
||||||
self.interruptSleep()
|
self.interruptSleep()
|
||||||
self.deleteStackDesc()
|
self.deleteStackDesc()
|
||||||
|
|
||||||
def clickHandler(self, event):
|
def clickHandler(self, event):
|
||||||
|
if self.stopWinAnimation(): return EVENT_PROPAGATE
|
||||||
self._defaultHandler()
|
self._defaultHandler()
|
||||||
self.event_handled = False
|
self.event_handled = False
|
||||||
return EVENT_PROPAGATE
|
return EVENT_PROPAGATE
|
||||||
|
|
||||||
def undoHandler(self, event):
|
def undoHandler(self, event):
|
||||||
if not self.app: return EVENT_PROPAGATE # FIXME (GTK)
|
if not self.app: return EVENT_PROPAGATE # FIXME (GTK)
|
||||||
|
if self.stopWinAnimation(): return EVENT_PROPAGATE
|
||||||
self._defaultHandler()
|
self._defaultHandler()
|
||||||
if self.demo:
|
if self.demo:
|
||||||
self.stopDemo()
|
self.stopDemo()
|
||||||
|
@ -798,6 +814,7 @@ class Game:
|
||||||
|
|
||||||
def redoHandler(self, event):
|
def redoHandler(self, event):
|
||||||
if not self.app: return EVENT_PROPAGATE # FIXME (GTK)
|
if not self.app: return EVENT_PROPAGATE # FIXME (GTK)
|
||||||
|
if self.stopWinAnimation(): return EVENT_PROPAGATE
|
||||||
self._defaultHandler()
|
self._defaultHandler()
|
||||||
if self.demo:
|
if self.demo:
|
||||||
self.stopDemo()
|
self.stopDemo()
|
||||||
|
@ -1073,13 +1090,114 @@ class Game:
|
||||||
canvas.move(id, ddx, ddy)
|
canvas.move(id, ddx, ddy)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def doWinAnimation(self):
|
||||||
|
# based on code from pygtk-demo
|
||||||
|
import Image, ImageTk
|
||||||
|
|
||||||
|
FRAME_DELAY = 40
|
||||||
|
CYCLE_LEN = 60
|
||||||
|
images = self.win_animation.images
|
||||||
|
saved_images = self.win_animation.saved_images # cached images
|
||||||
|
canvas = self.canvas
|
||||||
|
|
||||||
|
x0 = int(int(canvas.cget('width'))*(canvas.xview()[0]))
|
||||||
|
y0 = int(int(canvas.cget('height'))*(canvas.yview()[0]))
|
||||||
|
width, height = self.win_animation.width, self.win_animation.height
|
||||||
|
|
||||||
|
tmp_tk_images = []
|
||||||
|
raised_images = []
|
||||||
|
n_images = len(images)
|
||||||
|
xmid = width / 2.0
|
||||||
|
ymid = height / 2.0
|
||||||
|
radius = min(xmid, ymid) / 2.0
|
||||||
|
|
||||||
|
f = float(self.win_animation.frame_num % CYCLE_LEN) / float(CYCLE_LEN)
|
||||||
|
r = radius +(radius / 3.0) * math.sin(f * 2.0 * math.pi)
|
||||||
|
img_index = 0
|
||||||
|
|
||||||
|
for im in images:
|
||||||
|
|
||||||
|
iw, ih = im.size
|
||||||
|
|
||||||
|
ang = 2.0 * math.pi * img_index / n_images - f * 2.0 * math.pi
|
||||||
|
xpos = x0 + int(xmid + r * math.cos(ang) - iw / 2.0)
|
||||||
|
ypos = y0 + int(ymid + r * math.sin(ang) - ih / 2.0)
|
||||||
|
|
||||||
|
if img_index & 1:
|
||||||
|
k = math.sin(f * 2.0 * math.pi)
|
||||||
|
else:
|
||||||
|
k = math.cos(f * 2.0 * math.pi)
|
||||||
|
k = k * k
|
||||||
|
k = max(0.4, k)
|
||||||
|
round_k = int(round(k*100))
|
||||||
|
if img_index not in saved_images:
|
||||||
|
saved_images[img_index] = {}
|
||||||
|
if round_k == 100:
|
||||||
|
tmp = im
|
||||||
|
elif round_k in saved_images[img_index]:
|
||||||
|
tmp = saved_images[img_index][round_k]
|
||||||
|
else:
|
||||||
|
new_size = (int(iw*k), int(ih*k))
|
||||||
|
tmp = im.resize(new_size, resample=Image.BICUBIC)
|
||||||
|
saved_images[img_index][round_k] = tmp
|
||||||
|
|
||||||
|
tk_tmp = ImageTk.PhotoImage(image=tmp)
|
||||||
|
id = canvas.create_image(xpos, ypos, image=tk_tmp, anchor='nw')
|
||||||
|
if k > 0.6:
|
||||||
|
raised_images.append(id)
|
||||||
|
tmp_tk_images.append(tk_tmp)
|
||||||
|
|
||||||
|
img_index += 1
|
||||||
|
|
||||||
|
for id in raised_images:
|
||||||
|
canvas.tag_raise(id)
|
||||||
|
self.win_animation.frame_num = (self.win_animation.frame_num+1) % CYCLE_LEN
|
||||||
|
self.win_animation.tk_images = tmp_tk_images
|
||||||
|
canvas.update_idletasks()
|
||||||
|
# loop
|
||||||
|
self.win_animation.timer = after(canvas, FRAME_DELAY, self.doWinAnimation)
|
||||||
|
|
||||||
|
def stopWinAnimation(self):
|
||||||
|
if self.win_animation.timer:
|
||||||
|
after_cancel(self.win_animation.timer) # stop loop
|
||||||
|
self.win_animation.timer = None
|
||||||
|
self.win_animation.tk_images = [] # delete all images
|
||||||
|
self.saved_images = {}
|
||||||
|
self.canvas.showAllItems()
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
def winAnimation(self, perfect=0):
|
def winAnimation(self, perfect=0):
|
||||||
# Stupid animation when you win a game.
|
|
||||||
# FIXME: make this interruptible by a key- or mousepress
|
|
||||||
### if not self.app.opt.win_animation:
|
### if not self.app.opt.win_animation:
|
||||||
### return
|
### return
|
||||||
if not self.app.opt.animations:
|
if not self.app.opt.animations:
|
||||||
return
|
return
|
||||||
|
if TOOLKIT == 'gtk':
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
import Image
|
||||||
|
except ImportError:
|
||||||
|
return
|
||||||
|
self.canvas.hideAllItems()
|
||||||
|
# select some random cards
|
||||||
|
cards = self.cards[:]
|
||||||
|
scards = []
|
||||||
|
for i in xrange(10):
|
||||||
|
c = self.app.miscrandom.choice(cards)
|
||||||
|
scards.append(c)
|
||||||
|
cards.remove(c)
|
||||||
|
for c in scards:
|
||||||
|
self.win_animation.images.append(c._face_image._pil_image)
|
||||||
|
# compute visible geometry
|
||||||
|
self.win_animation.width = self.canvas.winfo_width()
|
||||||
|
self.win_animation.height = self.canvas.winfo_height()
|
||||||
|
# run win animation in background
|
||||||
|
after_idle(self.canvas, self.doWinAnimation)
|
||||||
|
return
|
||||||
|
|
||||||
|
def redealAnimation(self):
|
||||||
|
if not self.app.opt.animations or not self.app.opt.redeal_animation:
|
||||||
|
return
|
||||||
self.setCursor(cursor=CURSOR_WATCH)
|
self.setCursor(cursor=CURSOR_WATCH)
|
||||||
self.top.busyUpdate()
|
self.top.busyUpdate()
|
||||||
self.canvas.update_idletasks()
|
self.canvas.update_idletasks()
|
||||||
|
@ -1093,12 +1211,18 @@ class Game:
|
||||||
if s is not self.s.talon:
|
if s is not self.s.talon:
|
||||||
for c in s.cards:
|
for c in s.cards:
|
||||||
cards.append((c,s))
|
cards.append((c,s))
|
||||||
|
if not cards:
|
||||||
|
return
|
||||||
# select some random cards
|
# select some random cards
|
||||||
acards = []
|
acards = []
|
||||||
for i in range(16):
|
scards = cards[:]
|
||||||
c, s = self.app.miscrandom.choice(cards)
|
for i in range(12):
|
||||||
|
c, s = self.app.miscrandom.choice(scards)
|
||||||
if c not in acards:
|
if c not in acards:
|
||||||
acards.append(c)
|
acards.append(c)
|
||||||
|
scards.remove((c,s))
|
||||||
|
if not scards:
|
||||||
|
break
|
||||||
# animate
|
# animate
|
||||||
sx, sy = self.s.talon.x, self.s.talon.y
|
sx, sy = self.s.talon.x, self.s.talon.y
|
||||||
w, h = self.width, self.height
|
w, h = self.width, self.height
|
||||||
|
@ -1363,6 +1487,7 @@ You have reached
|
||||||
time = self.getTime()
|
time = self.getTime()
|
||||||
self.finished = True
|
self.finished = True
|
||||||
self.playSample("gameperfect", priority=1000)
|
self.playSample("gameperfect", priority=1000)
|
||||||
|
self.winAnimation(perfect=1)
|
||||||
d = MfxMessageDialog(self.top, title=_("Game won"),
|
d = MfxMessageDialog(self.top, title=_("Game won"),
|
||||||
text=_('''
|
text=_('''
|
||||||
Congratulations, this
|
Congratulations, this
|
||||||
|
@ -1379,6 +1504,7 @@ for %d moves.
|
||||||
time = self.getTime()
|
time = self.getTime()
|
||||||
self.finished = True
|
self.finished = True
|
||||||
self.playSample("gamewon", priority=1000)
|
self.playSample("gamewon", priority=1000)
|
||||||
|
self.winAnimation()
|
||||||
d = MfxMessageDialog(self.top, title=_("Game won"),
|
d = MfxMessageDialog(self.top, title=_("Game won"),
|
||||||
text=_('''
|
text=_('''
|
||||||
Congratulations, you did it !
|
Congratulations, you did it !
|
||||||
|
@ -1405,10 +1531,6 @@ for %d moves.
|
||||||
if d.status == 0 and d.button == 0:
|
if d.status == 0 and d.button == 0:
|
||||||
# new game
|
# new game
|
||||||
self.endGame()
|
self.endGame()
|
||||||
if status == 2:
|
|
||||||
self.winAnimation(perfect=1)
|
|
||||||
elif status == 1:
|
|
||||||
self.winAnimation()
|
|
||||||
self.newGame()
|
self.newGame()
|
||||||
elif d.status == 0 and d.button == 1:
|
elif d.status == 0 and d.button == 1:
|
||||||
# restart game
|
# restart game
|
||||||
|
|
|
@ -996,16 +996,17 @@ class Stack:
|
||||||
return EVENT_HANDLED
|
return EVENT_HANDLED
|
||||||
if self.game.app.opt.mouse_type == 'point-n-click':
|
if self.game.app.opt.mouse_type == 'point-n-click':
|
||||||
return EVENT_HANDLED
|
return EVENT_HANDLED
|
||||||
if self.game.app.opt.mouse_type == 'drag-n-drop' and TOOLKIT == 'tk':
|
self.keepDrag(event)
|
||||||
# use a timer to update the drag
|
## if self.game.app.opt.mouse_type == 'drag-n-drop' and TOOLKIT == 'tk':
|
||||||
# this allows us to skip redraws on slow machines
|
## # use a timer to update the drag
|
||||||
drag = self.game.drag
|
## # this allows us to skip redraws on slow machines
|
||||||
if drag.timer is None:
|
## drag = self.game.drag
|
||||||
drag.timer = after_idle(self.canvas, self.keepDragTimer)
|
## if drag.timer is None:
|
||||||
drag.event = event
|
## drag.timer = after_idle(self.canvas, self.keepDragTimer)
|
||||||
else:
|
## drag.event = event
|
||||||
# update now
|
## else:
|
||||||
self.keepDrag(event)
|
## # update now
|
||||||
|
## self.keepDrag(event)
|
||||||
return EVENT_HANDLED
|
return EVENT_HANDLED
|
||||||
|
|
||||||
def __releaseEventHandler(self, event):
|
def __releaseEventHandler(self, event):
|
||||||
|
|
Loading…
Add table
Reference in a new issue