+
+ l->ignore = false;
+ l->score = NULL;
+ gettimeofday(&now, NULL);
+ l->expires = now;
+ l->expires.tv_sec += EXPIRY_SECS;
+
+ line_object_setup(lines, &objects, l);
+ talloc_set_destructor(l, destroy_line);
+}
+
+static void redraw_ball(SDL_Surface *s, struct object *me)
+{
+ struct ball *b = container_of(me, struct ball, object);
+ SDL_Rect rect = { .x = b->pos.x - b->image->w/2,
+ .y = b->pos.y - b->image->h/2 };
+
+ SDL_BlitSurface(b->image, NULL, s, &rect);
+}
+
+static void redraw_score(SDL_Surface *s, struct object *me)
+{
+ struct score *score = container_of(me, struct score, object);
+ SDL_Rect rect = { .x = score->object.start.x,
+ .y = score->object.start.y };
+
+ SDL_BlitSurface(score->image, NULL, s, &rect);
+}
+
+static SDL_Surface *score(struct score *s)
+{
+ char filename[40];
+
+ s->value++;
+ SDL_FreeSurface(s->image);
+ sprintf(filename, "images/%u.png", s->value);
+ s->image = IMG_Load(filename);
+ /* No more images? You won! */
+ if (!s->image)
+ return s->won;
+
+ add_update(&s->object);
+ return NULL;
+}
+
+/* Due to rounding, we exaggerate bounding box by 1 here. */
+static void do_updates(struct list_head *objects, SDL_Surface *screen)
+{
+ struct object *i;
+ unsigned int y, startx, starty, endx, endy;
+
+ /* Clip */
+ if (start_update.x <= 0)
+ startx = 0;
+ else
+ startx = start_update.x - 1;
+ if (start_update.y <= 0)
+ starty = 0;
+ else
+ starty = start_update.y - 1;
+
+ endx = end_update.x+1;
+ endy = end_update.y+1;
+
+ if (endx > screen->w)
+ endx = screen->w;
+ if (endy > screen->h)
+ endy = screen->h;
+
+ SDL_LockSurface(screen);
+ /* First we clear the area to white. */
+ for (y = starty; y < endy; y++) {
+ memset(screen->pixels + y * screen->pitch
+ + screen->format->BytesPerPixel * startx,
+ 0xFF,
+ (endx - startx) * screen->format->BytesPerPixel);
+ }
+ SDL_UnlockSurface(screen);
+
+ /* Now redraw everything which overlaps it */
+ list_for_each(objects, i, list) {
+ if (i->end.x < startx)
+ continue;
+ if (i->end.y < starty)
+ continue;
+ if (i->start.x > endx)
+ continue;
+ if (i->start.y > endy)
+ continue;
+ i->redraw(screen, i);
+ }
+
+ SDL_UpdateRect(screen, startx, starty, endx - startx, endy - starty);
+
+ /* Reset bounding box */
+ needs_update = false;