Search code examples
common-lispsdlsbclsdl-image

Lispbuilder-SDL: turn surface and preserve color key (transparency)


Explanation

I'm writing turtle graphics app in CL using SDL. I've created a drawing of a turtle and saved it in PNG. Snag No 1: SDL:LOAD-IMAGE didn't work well with actual transparency in the image. So, I've colored transparent parts with white color and did

(sdl:load-image
 (merge-pathnames #P"resources/turtle.png"
                  (asdf:system-source-directory :cl-turtle))
 :image-type :png
 :color-key sdl:*white*)

So, :COLOR-KEY option says that all SDL:*WHITE* pixels will be transparent. And this works: drawing the turtle on the yellow background showed no white pixels.

However, I would like my turtle to point into a particular direction and change it in the response to TURN command. One suggestion I've found was to use the sprites for all possible angles, but this won't work nicely for the turtle: too many directions.

So, I've loaded LISPBUILDER-SDL-GFX, to use SDL:ROTATE-SURFACE-XY. And it does rotate the the turtle fine. And I can see, that SDL:*WHITE* is set as color-key and color-keying is enabled in the rotated surface. However, when I draw it, white color is still rendered. Is there a way to fix this?

Full code

(ql:quickload '(:lispbuilder-sdl :lispbuilder-sdl-image :lispbuilder-sdl-gfx :vom))

(defstruct turtle
  direction
  x
  y
  scale)

(defun draw-turtle (turtle image)
  ;; (format t "~&GFX? ~A~%" lispbuilder-sdl-cffi::*gfx-loaded-p*)
  (let ((img (sdl:rotate-surface-xy (mod (turtle-direction turtle) 360)
                                    :surface image)))
    (setf (sdl::color-key img) sdl:*white*)
    (setf (sdl:color-key-enabled-p img) t)
    (vom:info "Color key enabled (img)?: ~A" (sdl:color-key-enabled-p img))
    (vom:info "Color key is: ~A" (slot-value (sdl:color-key img) 'sdl::color-vector))
    (sdl:draw-surface-at-* img
                           (turtle-x turtle)
                           (turtle-y turtle))))

(defun turtle ()
  (sdl:with-init()
    (sdl:window 500 500
                :title-caption "Turtle")
    (setf (sdl:frame-rate) 1)
    (let ((turtle-image (sdl:load-image
                         (merge-pathnames #P"resources/turtle.png"
                                          (asdf:system-source-directory :cl-turtle))
                         :image-type :png
                         :color-key sdl:*white*))
          (turtle (make-turtle :direction 30 :x 200 :y 200 :scale 1)))
     (sdl:with-events ()
       (:quit-event () t)
       (:key-down-event () (sdl:push-quit-event))
       (:idle ()
              (sdl:clear-display sdl:*yellow*)
              (draw-turtle turtle turtle-image)
              (sdl:update-display))))))

(turtle)

Log(VOM) output

  <INFO> [14:24:35] cl-turtle - Color key enabled (img)?: T
  <INFO> [14:24:35] cl-turtle - Color key is: #(255 255 255)

Screenshot

Turtle screenshot

System info

Ubuntu 16.04 with libSDL-1.2.so.0.11.4, libSDL_gfx.so.15.9.1 and libSDL_image-1.2.so.0.8.4

SBCL 1.3.7 (from roswell sbcl-bin)


Solution

  • Apparently, calling sdl:load-and-convert-image instead of sdl:load-image fixes the issue.

    Loads an image from the filename SOURCE as per LOAD-IMAGE-*, converts this image to the current display format using SDL:CONVERT-SURFACE.

    Parameters supported are the same as those for LOAD-IMAGE and SDL:CONVERT-IMAGE.