Reply
Thread Tools
zeez's Avatar
Posts: 341 | Thanked: 68 times | Joined on Aug 2007
#1
Hi !

I wrote a little app in python that downloads Calvin & Hobbes comics from the web and displays them on the N800.
I use a little "animation" as a transition between strips. However since i'm really new to pygame my implementation is probably very bad. So i was hoping someone here could point out how to make the animation smoother.

Thanks!

Keys:
Back -> Exit
Fullscreen -> Toggles Fullscreen (also app is made for fullscreen)
zoomin/out -> toggle scaling
d-pad center: next strip
d-pad right: next strip with animation

http://www.vdecine.net/Calvin.tar.gz
 
Posts: 883 | Thanked: 980 times | Joined on Jul 2007 @ Bern, Switzerland
#2
Hello Zeez

Thank you very much for your wonderful little app - it finally motivated me to start Python dev on the N800

From what I picked up about PyGame, one possible way to improve the performance of the animation would be to use the Sprite module of PyGame, handling the two strips as sprites. Hadn't yet time to test this.

In the meantime, I made 4 modifications to your code:
  • Animation comes in from right to left now (seems more natural)
  • Strips change automaticall every 5 seconds. D-Pad Down to disable/enable (status icon shows red/green in topleft corner)
  • Reset strips and show first one: D-Pad Up ((status icon shows blue in topleft corner)
  • Touching the screen moves to the next strip, too (just like D-Pad Right)
Another minor optimisation you could do: Re-compress the included status images , they are way too big for what they contain. You might safely compress them much more with JPEG.

Ah the joy of coding.
Thanks again, mate!
Code:
#!/usr/bin/python

import pygame
from pygame.locals import *
import os
import urllib
import time
import datetime
import thread

EVT_STEP = pygame.USEREVENT
path = './strips/'
bTimerRunning = False

# Class that handles the strip "database"
class strips:
 def __init__(self):
  self.availableStrips = []
  self.readStrips = self.loadReadStrips()
  self.currentStrip = ''

 # Get list of read strips from file
 def loadReadStrips(self):
  read = []
  for line in open('read.log','rw').readlines():
   line=line[0:len(line)-1]
   if (line!=''):
    read.append(line)
  return read

 # Save current list of read strips to file
 def saveReadStrips(self):
  file = open('read.log', 'w')
  for strip in self.readStrips:
   file.write(strip + '\n')

 # Save current list of read strips to file
 def resetReadStrips(self):
  self.readStrips = []
  self.availableStrips = []
  file = open('read.log', 'w')
  file.write('\n')
  self.get()
  self.currentStrip = self.getFirst()
  return self.currentStrip

 # Locally save a strip from the web
 def saveUrlToFile(self, url, fileName):
  try:
   f = open( fileName, 'wb' )
   data = urllib.urlopen(url).read()
   f.write( data )
   f.close()
   return 1
  except:
   return 0

 # Get available strips
 def get(self):
  now = datetime.date.today()
  today = now.strftime("%y%m%d")
  for i in range(30):					# Usually there are strips avail. for the last 30 days
   delta = datetime.timedelta(days=-i)
   now2 = now + delta
   date = now2.strftime("%y%m%d")

   if ('ch' + date + '.gif' not in self.readStrips):		# Make sure strip has not been read
    if (os.path.isfile(path + 'ch' + date + '.gif') and os.path.getsize(path + 'ch' + date + '.gif') > 5000):
      self.availableStrips.append('ch' + date + '.gif')
    elif(self.saveUrlToFile('http://images.ucomics.com/comics/ch/2007/ch' + date + '.gif',path + 'ch' + date + '.gif')):
     self.availableStrips.append('ch' + date + '.gif')

 # Return the next unread strip (which is the oldest unread)
 def getNext(self):
  if (len(self.availableStrips) > 0):
   self.currentStrip = self.availableStrips.pop()
   self.readStrips.append(self.currentStrip)
   return self.currentStrip
  else:
   return 'nomore.jpg'

 # Return the first unread strip
 def getFirst(self):
  if (len(self.availableStrips) > 0):
   self.currentStrip = self.availableStrips[0]
   return self.currentStrip
  else:
   return 'nomore.jpg'

# Class that handles all display stuff
class display:
 def __init__(self):
  pygame.init()
  self.scale = False
  self.screen = pygame.display.set_mode((800,480),FULLSCREEN,16)
  self.back = pygame.image.load(os.path.join(".","chback.gif"))

 # Let the user know we're downloading the strips
 def showLoading(self):
  load = pygame.image.load(os.path.join(".","loading.jpg")).convert()
  self.screen.blit(load,(0,0))
  pygame.display.flip()

 # Load  file and return surface
 def loadFile(self,file):
  try:
   strip = pygame.image.load(os.path.join(path, file)).convert()
   if (self.scale==True):
    if (strip.get_height() > 200):
     strip = pygame.transform.scale(strip, (691,480))
    else:
     strip = pygame.transform.scale(strip, (800,252))
  except:
   strip = pygame.image.load(os.path.join('.', 'nomore.jpg')).convert()
  return strip

 # Show a strip without anymation (currently just the first one)
 def showStrip(self,strip):
  stripSur = self.loadFile(strip)
  self.screen.blit(self.back,(0,0))
  self.screen.blit(stripSur,((800-stripSur.get_width())/2,(480-stripSur.get_height())/2))
  pygame.display.flip()

 def switchStrips(self,strip1,strip2):
  strip1Sur = self.loadFile(strip1)
  strip2Sur = self.loadFile(strip2)

  for x in range(81):
   self.screen.blit(self.back,(0,0))
#   self.screen.blit(strip1Sur,((800-strip1Sur.get_width())/2+10*x,(480-strip1Sur.get_height())/2))
#   self.screen.blit(strip2Sur,((((800-strip2Sur.get_width())/2)+10*x)-800,(480-strip2Sur.get_height())/2))
   self.screen.blit(strip1Sur,(((800-strip1Sur.get_width())/2+10*x)*-1,(480-strip1Sur.get_height())/2))
   self.screen.blit(strip2Sur,((((800-strip2Sur.get_width())/2)-10*x)+800,(480-strip2Sur.get_height())/2))
   pygame.display.flip()

 def animatedTransition(self, s, d):
     s.saveReadStrips()
     d.showStrip(s.getNext())

 def SwitchTimer(self,bTimer):
    if(bTimer == True):
      pygame.time.set_timer(EVT_STEP, 0)
      bTimer = False
      color = (255, 128, 128)
    else:
      pygame.time.set_timer(EVT_STEP, 10000)
      bTimer = True
      color = (128, 255, 128)
    statusIcon = pygame.Surface((10, 10))
    statusIcon.fill(color)
    self.screen.blit(statusIcon, (10,10))
    pygame.display.flip()
    return bTimer

if __name__ == '__main__':
 s = strips()
 d = display()

 # Check for new strips
 d.showLoading()
 s.get()

 # Show the first one automatically
 d.showStrip(s.getNext())

 #start the timer
 bTimerRunning = d.SwitchTimer(bTimerRunning)

 #disable the cursor
 pygame.mouse.set_visible(False)

 # Wait for user input
 while True:
  event = pygame.event.wait()
  if (event.type == KEYUP):
   if (event.key == 287):			# Fullscreen button / F6 : Toggle fullscreen
     pygame.display.toggle_fullscreen()
   if (event.key != K_ESCAPE):			# Esc/Back button -> Exit
    if (event.key == 13):            # DPad-center -> show next strip
     s.saveReadStrips()
     d.showStrip(s.getNext())
    if (event.key == 275):			# DPad-right -> show next strip (animated)
     s.saveReadStrips()
     d.switchStrips(s.currentStrip,s.getNext())
    if (event.key == 274):            # DPad-down -> enable/disable timer
     bTimerRunning = d.SwitchTimer(bTimerRunning)
    if (event.key == 273):            # DPad-up -> restart fro 1st picture, reset list
     color = (128, 128, 255)
     statusIcon = pygame.Surface((10, 10))
     statusIcon.fill(color)
     d.screen.blit(statusIcon, (10,10))
     pygame.display.flip()
     d.showStrip(s.resetReadStrips())
    if (event.key == 289):			# Zoom out -> No Scale
     d.scale = False
     d.showStrip(s.currentStrip)
    if (event.key == 288):			# Zoom in -> Scale strips to screen
     d.scale = True
     d.showStrip(s.currentStrip)
   else:
    break
  if (event.type == EVT_STEP):    #Timer-Event
   s.saveReadStrips()
   d.switchStrips(s.currentStrip,s.getNext())
  if (event.type == MOUSEBUTTONDOWN):    #Touchscreen-Event
   s.saveReadStrips()
   d.switchStrips(s.currentStrip,s.getNext())
 
Reply

Thread Tools

 
Forum Jump


All times are GMT. The time now is 08:12.