[pygame] Animating a board of LED

[pygame] Animating a board of LED

Postby hsn6 » Thu Jul 18, 2013 5:31 am

Hi to all
I'm newbie in the python and this is my first program in it.
I have created a board that it LEDs can on/off like the checkbox. and a Timeline that has 20 Frames for controlling the animation (Frames are like the RadioButton).
Can you help me :

Frames would can save their Frames (on/off). (now they are saving all status to theirselve)
this timeline would works as well for playing animation.
Thank you for your replying!

Code: Select all
import pygame

pygame.init()



size = (800, 600)
screen = pygame.display.set_mode(size)
pygame.display.set_caption("Tablo")

black    = (   0,   0,   0)
white    = ( 255, 255, 255)
green    = (   0, 255,   0)
red      = ( 255,   0,   0)
blue     = (   0,   0, 255) 



done = False

first_nps = True

first_kh = True

ni = 0
nj = 0
nps = 0
R = {}
F = 0
FC = {}


clock = pygame.time.Clock()



while done == False:
  #Event processing:
  for event in pygame.event.get():
    if event.type == pygame.QUIT:
      done = True
    p = pygame.mouse.get_pos()
    x = p[0]
    y = p[1]
    ms = pygame.mouse.get_pressed()
  #Event processing
 
  #Draw Table
  for x_offest in range(0, 850, 50):
    pygame.draw.line(screen, blue, (x_offest, 0), (x_offest, 400), 5)
  for y_offest in range(0, 650, 50):
    pygame.draw.line(screen, blue, (0 , y_offest), (800 , y_offest), 5)
  pygame.draw.line(screen, black, (0 , 0 + 500), (800 ,  500), 5)
  #Draw Table

  #on/off LEDs
  if ms == (1,0,0):
    for i in range(0, 800, 50):
      for j in range(0, 400,50):
        if x > i and x < i + 50 and y > j and y < j + 50:
          ni = i / 50
          nis = str(ni)
          nj = j / 50
          njs = str(nj)
          nps = nis + njs
         
          if R.has_key(nps) == 0:
            pygame.draw.circle(screen, red, (i + 25, j+ 25), 20, 20)
            R[nps] = 1
            pygame.time.delay(200)
          else:
            pygame.draw.circle(screen, black, (i + 25, j + 25), 20, 20)
            del R[nps]
            pygame.time.delay(200)
         
          pygame.display.flip()
  #on/off LEDs

  #Draw Timeline
  for x_offest in range(0, 800, 40):
    pygame.draw.line(screen, white, (x_offest, 450), (x_offest, 550), 4)
  #Draw Timeline
    if ms == (1,0,0) and x > x_offest and x < x_offest + 40 and y > 450 and y < 550:
      fi = x_offest / 40
      F = fi + 1
      FC[F] = R
      print FC
       
          #Frames radio button
      for gclearer in range(0, 800, 40):
        pygame.draw.circle(screen, black, (gclearer + 20, 500), 15 , 4)
      pygame.draw.circle(screen, green, (x_offest + 20, 500), 15 , 4)
          #Frames radio button
               
               
       
       
      pygame.time.delay(50)
      pygame.display.flip() 

  pygame.display.flip()
  clock.tick(25)
Last edited by Yoriz on Mon Jul 22, 2013 4:45 pm, edited 1 time in total.
Reason: changed title and moved to game devlopment
hsn6
 
Posts: 3
Joined: Thu Jul 18, 2013 4:49 am

Re: Animating a board of LED

Postby Mekire » Thu Jul 18, 2013 6:13 am

I took a look at this, and while it is very impressive if this really is your first program, I think you should take a step back. Almost none of your variables have meaningful names, which is honestly alone enough to make me not want to go through it. Also the entire thing is in the global scope. On the conventions side, please use 4-space tabs (most good IDEs can be set up so the tab key adds 4 spaces, not one tab), and capitalize GLOBAL_CONSTANTS. I know you probably don't want to hear this, but learning functions is something you should do before trying to do anything with graphics.

A few technical things with pygame. Stay away from pygame.time.delay. It really isn't what you want. You can limit your programs global framerate with:
Code: Select all
pygame.time.Clock.tick(frame_rate_here)
Beyond that, for things that require individual timers use:
Code: Select all
pygame.time.get_ticks()
Also, unless you have a very good reason, you should not be calling pygame.display.flip or pygame.display.update in multiple places. Call one or the other once each time through your game loop, after everything that was meant to update that frame has updated.
Also I'm sure you have noticed the annoying patterns on your circles. This isn't your fault, but in pygame (or rather SDL) circles won't draw properly here if you use the border width argument. If you want to avoid this draw only solid circles. They won't have the pattern.

ie a circle with a thin radius could be:
Code: Select all
import sys
import pygame

RED = (255,0,0)
CLEAR = (0,0,0,0)
GREY = (100,100,100)

def run_it():
    pygame.init()
    screen = pygame.display.set_mode((400,400))
    screen_rect = screen.get_rect()
    clock = pygame.time.Clock()
    done = False
    while not done:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                done = True
        screen.fill(GREY)
        circle_surface = pygame.Surface((400,400)).convert_alpha()
        circle_surface.fill(CLEAR)
        pygame.draw.circle(circle_surface,RED,screen_rect.center,50)
        pygame.draw.circle(circle_surface,CLEAR,screen_rect.center,40)
        screen.blit(circle_surface,(0,0))
        pygame.display.update()
        clock.tick(60)

if __name__ == "__main__":
    run_it()
    pygame.quit()
    sys.exit()

Good luck to you. If you can clean up the code a little bit I will take closer look.
-Mek
User avatar
Mekire
 
Posts: 988
Joined: Thu Feb 07, 2013 11:33 pm
Location: Amakusa, Japan

Re: Animating a board of LED

Postby hsn6 » Fri Jul 19, 2013 10:28 am

I gave the suitable name for variables and I clean the code from placeless delay and flip. for next program i'll use 4 spaces.
do you can help me now? :D

Code: Select all
import pygame

pygame.init()



size = (800, 600)
screen = pygame.display.set_mode(size)
pygame.display.set_caption("Tablo")

black    = (   0,   0,   0)
white    = ( 255, 255, 255)
green    = (   0, 255,   0)
red      = ( 255,   0,   0)
blue     = (   0,   0, 255) 



done = False
first_mouse_event = True


LEDs_on = {}
current_frame = 0
Timeline = {}


clock = pygame.time.Clock()



while done == False:
  #Event processing:
  for event in pygame.event.get():
    if event.type == pygame.QUIT:
      done = True
    mouse_postion = pygame.mouse.get_pos()
    x_mouse = mouse_postion[0]
    y_mouse = mouse_postion[1]
    mouse_status = pygame.mouse.get_pressed()
  #Event processing
 
  #Draw Table
  for x_offest in range(0, 850, 50):
    pygame.draw.line(screen, blue, (x_offest, 0), (x_offest, 400), 5)
  for y_offest in range(0, 650, 50):
    pygame.draw.line(screen, blue, (0 , y_offest), (800 , y_offest), 5)
  pygame.draw.line(screen, black, (0 , 0 + 500), (800 ,  500), 5)
  #Draw Table

  #on/off LEDs
  first_mouse_event = True
  if mouse_status == (1, 0, 0):
    for i in range(0, 800, 50):
      for j in range(0, 400,50):
        if x_mouse > i and x_mouse < i + 50 and y_mouse > j and y_mouse < j + 50:
          column_number = i / 50
          column_number_string = str(column_number)
          row_number = j / 50
          row_number_string = str(row_number)
          location_string = column_number_string + row_number_string
         
          if LEDs_on.has_key(location_string) == 0:
            pygame.draw.circle(screen, red, (i + 25, j+ 25), 20, 20)
            while first_mouse_event:
             for event in pygame.event.get():
              mouse_status = pygame.mouse.get_pressed()
              if mouse_status == (0, 0, 0):
                LEDs_on[location_string] = 1
                first_mouse_event = False
          else:
            pygame.draw.circle(screen, black, (i + 25, j + 25), 20, 20)
            while first_mouse_event:
             for event in pygame.event.get():
              mouse_status = pygame.mouse.get_pressed()
              if mouse_status == (0, 0, 0):
                del LEDs_on[location_string]
                first_mouse_event = False
           

  #on/off LEDs

  #Draw Timeline
  for x_offset in range(0, 800, 40):
    pygame.draw.line(screen, white, (x_offset, 450), (x_offset, 550), 4)
  #Draw Timeline
    if mouse_status == (1,0,0) and x_mouse > x_offset and x_mouse < x_offset + 40 and y_mouse > 450 and y_mouse < 550:
      current_frame = x_offset / 40 + 1
      Timeline[current_frame] = LEDs_on
      print Timeline
       
          #Frames radio button
      for other_frame_cleaner in range(0, 800, 40):
        pygame.draw.circle(screen, black, (other_frame_cleaner + 20, 500), 15 , 4)
      pygame.draw.circle(screen, green, (x_offset + 20, 500), 15 , 4)
          #Frames radio button
               
               
       
         

  pygame.display.flip()
  clock.tick(25)
hsn6
 
Posts: 3
Joined: Thu Jul 18, 2013 4:49 am

Re: Animating a board of LED

Postby Mekire » Mon Jul 22, 2013 1:39 am

Well as I said, functions are necessary for a program of this type (if you want it to have any sort of logical coherency). Personally I wouldn't code a program like this without classes and functions.

I can show you how I would implement this but you will need to learn classes and functions to understand what is going on.

Left mouse to add cells and change frame; right to delete cells; spacebar to start/stop animation of currently existing frames:
Code: Select all
import sys,os
import pygame as pg


SCREEN_SIZE = (805, 600)
CELL_SIZE = (50,50)
TIMELINE_CELL_SIZE = (40,100)

BLACK = (0,0,0)
WHITE = (255,255,255)
GREEN = (0,255,0)
RED   = (255,0,0)
BLUE  = (0,0,255)


class Control(object):
    def __init__(self):
        os.environ["SDL_VIDEO_CENTERED"] = '1'
        pg.init()
        pg.display.set_caption("Tablo")
        self.screen = pg.display.set_mode(SCREEN_SIZE)
        self.done = False
        self.clock = pg.time.Clock()
        self.fps = 60
        self.grid_image = self.make_grid()
        self.grid_rect = pg.Rect(0,0,800,400)
        self.timeline_rect = pg.Rect(0,450,800,100)
        self.frames = [None for i in xrange(20)]
        self.current_frame = 0
        self.frames[self.current_frame] = Frame()
        self.animate = False
        self.animate_frame = 0
        self.animate_frames = []
        self.animate_fps = 5.0
        self.timer = 0.0

    def make_grid(self):
        image = pg.Surface(SCREEN_SIZE).convert()
        for i in xrange(0,SCREEN_SIZE[0]+50,50):
            image.fill(BLUE,(i,0,5,400))
        for j in xrange(0,SCREEN_SIZE[1]+50,50):
            image.fill(BLUE,(0,j,SCREEN_SIZE[0],5))
        image.fill(BLACK,(0,500,SCREEN_SIZE[0],5))
        for i in range(0,SCREEN_SIZE[0],40):
            image.fill(WHITE,(i,450,5,105))
        return image

    def get_target(self,mouse,cell_size):
        return mouse[0]//cell_size[0],mouse[1]//cell_size[1]

    def draw_frame_select(self):
        location = (5+self.current_frame*TIMELINE_CELL_SIZE[0],450+5)
        size = TIMELINE_CELL_SIZE[0]-5,TIMELINE_CELL_SIZE[1]-5
        rect = pg.Rect((0,0),size)
        image = pg.Surface(size).convert_alpha()
        image.fill((0,0,0,0))
        pg.draw.circle(image,GREEN,rect.center,15)
        pg.draw.circle(image,(0,0,0,0),rect.center,10)
        self.screen.blit(image,rect.move(location))

    def draw_nonempty_frames(self):
        for i,frame in enumerate(self.frames):
            if frame:
                self.fill_timeline_frame(i,(75,75,255))

    def fill_timeline_frame(self,index,color):
        location = (5+index*TIMELINE_CELL_SIZE[0],450+5)
        size = TIMELINE_CELL_SIZE[0]-5,TIMELINE_CELL_SIZE[1]-5
        rect = pg.Rect(location,size)
        self.screen.fill(color,rect)

    def animating(self):
        current_time = pg.time.get_ticks()
        if current_time-self.timer > 1000/self.animate_fps:
            self.animate_frame = (self.animate_frame+1)%len(self.animate_frames)
            self.timer = current_time
        index,frame = self.animate_frames[self.animate_frame]
        frame.update(self.screen)
        self.fill_timeline_frame(index,GREEN)

    def change_frame(self,coord):
        current_dict = self.frames[self.current_frame].cell_dict
        self.current_frame = coord
        if not self.frames[self.current_frame]:
            self.frames[self.current_frame] = Frame(current_dict)

    def event_loop(self):
        for event in pg.event.get():
            if event.type == pg.QUIT:
              self.done = True
            elif event.type == pg.MOUSEBUTTONDOWN:
                self.process_mouse_events(event)
            elif event.type == pg.KEYDOWN:
                if event.key == pg.K_SPACE:
                    self.setup_animation()

    def process_mouse_events(self,event):
        if not self.animate:
            if self.grid_rect.collidepoint(event.pos):
                coord = self.get_target(event.pos,CELL_SIZE)
                if event.button == 1:
                    self.frames[self.current_frame].add_cell(coord)
                elif event.button == 3:
                    self.frames[self.current_frame].delete_cell(coord)
            elif self.timeline_rect.collidepoint(event.pos):
                if event.button == 1:
                    coord = self.get_target(event.pos,TIMELINE_CELL_SIZE)
                    self.change_frame(coord[0])

    def setup_animation(self):
        self.animate = not self.animate
        self.animate_frames = [(i,frame) for (i,frame) in enumerate(self.frames) if frame]
        self.animate_frame = 0
        self.timer = pg.time.get_ticks()

    def update(self):
        self.screen.blit(self.grid_image,(0,0))
        if not self.animate:
            self.frames[self.current_frame].update(self.screen)
            self.draw_nonempty_frames()
            self.draw_frame_select()
        else:
            self.draw_nonempty_frames()
            self.animating()

    def game_loop(self):
        while not self.done:
            self.event_loop()
            self.update()
            pg.display.update()
            self.clock.tick(self.fps)


class Frame(object):
    def __init__(self,cell_dict=None):
        if cell_dict:
            self.cell_dict = cell_dict.copy()
        else:
            self.cell_dict = {}

    def update(self,surface):
        for cell in self.cell_dict:
            location = 6+cell[0]*CELL_SIZE[0],5+cell[1]*CELL_SIZE[1]
            size = CELL_SIZE[0]-5,CELL_SIZE[1]-5
            rect = pg.Rect(location,size)
            pg.draw.circle(surface,RED,rect.center,15)

    def add_cell(self,coords):
        self.cell_dict[coords] = True

    def delete_cell(self,coords):
        if coords in self.cell_dict:
            self.cell_dict.pop(coords)


if __name__ == "__main__":
    run_it = Control()
    run_it.game_loop()
    pg.quit();sys.exit()

The above could certainly still be cleaned up more; but the general idea is there.
-Mek
User avatar
Mekire
 
Posts: 988
Joined: Thu Feb 07, 2013 11:33 pm
Location: Amakusa, Japan

Re: Animating a board of LED

Postby hsn6 » Mon Jul 22, 2013 6:46 am

Thank you very much :)
I must read more about Classes and Functions.
which resources are best for this subjects and you suggest for me?
hsn6
 
Posts: 3
Joined: Thu Jul 18, 2013 4:49 am

Re: Animating a board of LED

Postby Mekire » Mon Jul 22, 2013 7:40 am

You should be able to find tons of resources fairly easily.

You could start with the official tutorial:
http://docs.python.org/2/tutorial/classes.html

Maybe try Dive Into Python.

Or if you want something interactive you could take a look at the Python section at Codecademy, though they are a bit simplistic.

-Mek
User avatar
Mekire
 
Posts: 988
Joined: Thu Feb 07, 2013 11:33 pm
Location: Amakusa, Japan


Return to Game Development

Who is online

Users browsing this forum: W3C [Linkcheck] and 1 guest