(module tilemap * (import scheme (chicken io) (chicken base) (chicken string) (chicken process-context) (chicken pathname) (chicken pretty-print) (srfi 1) expat defstruct) (defstruct tileset tilewidth tileheight spacing tilecount columns image-source image) (defstruct layer name width height map) (defstruct object name type x y width height properties) (defstruct tilemap width height tilewidth tileheight tileset-source tileset layers objects) (define (maybe-do action) (lambda (value) (if (eq? value #f) #f (action value)))) (define (attempt action) (lambda (value) (or (action value) value))) (define maybe-string->number (maybe-do (attempt string->number))) (define (string-alist->alist string-alist) (map (lambda (pair) (cons (string->symbol (car pair)) (maybe-string->number (cdr pair)))) string-alist)) (define (parse-tileset string-tileset) (let ((parser (expat:make-parser)) (tags '()) (tileset (make-tileset 0 0 0 0 0 ""))) (expat:set-start-handler! parser (lambda (tag attrs) (let ((symbol-attrs (string-alist->alist attrs))) (cond ((string=? tag "tileset") (set! tileset (alist->tileset symbol-attrs))) ((string=? tag "image") (tileset-image-source-set! tileset (alist-ref 'source symbol-attrs))))) (set! tags (cons tag tags)))) (expat:set-end-handler! parser (lambda (tag) (set! tags (cdr tags)))) (expat:set-character-data-handler! parser (lambda (line) #f)) (expat:parse parser string-tileset) tileset)) (define (load-tileset file-name) (call-with-input-file file-name (lambda (port) (parse-tileset (read-string #f port)) ;; Load up the image from SDL. ))) (define (parse-tilemap string-tilemap) (let ((parser (expat:make-parser)) (tags '()) (tilemap (make-tilemap 0 0 0 0 '() '() '())) (layer '())) (expat:set-start-handler! parser (lambda (tag attrs) (let ((symbol-attrs (string-alist->alist attrs))) (cond ((string=? tag "map") (tilemap-width-set! tilemap (alist-ref 'width symbol-attrs)) (tilemap-height-set! tilemap (alist-ref 'height symbol-attrs)) (tilemap-tilewidth-set! tilemap (alist-ref 'tilewidth symbol-attrs)) (tilemap-tileheight-set! tilemap (alist-ref 'tileheight symbol-attrs))) ((string=? tag "tileset") (tilemap-tileset-source-set! tilemap (alist-ref 'source symbol-attrs))) ((string=? tag "layer") (set! layer (alist->layer attrs))) ((string=? tag "object") (tilemap-objects-set! tilemap (cons (alist->object symbol-attrs) (tilemap-objects tilemap))))) (set! tags (cons tag tags))))) (expat:set-end-handler! parser (lambda (tag) (when (string=? tag "layer") (tilemap-layers-set! tilemap (cons layer (tilemap-layers tilemap))) (set! layer '())) (set! tags (cdr tags)))) (expat:set-character-data-handler! parser (lambda (line) (when (string=? (car tags) "data") (let ((txt (string-chomp line))) (when (not (string=? txt "")) (layer-map-set! layer (append (or (layer-map layer) '()) (list (map string->number (string-split txt ",")))))))))) (expat:parse parser string-tilemap) tilemap)) (define (load-tilemap file-name) (call-with-input-file file-name (lambda (port) (let ((tilemap (parse-tilemap (read-string #f port)))) (tilemap-tileset-set! tilemap (load-tileset (tilemap-tileset-source tilemap)))) ))) (when #f (let ((txt " ")) (tileset-image (parse-tileset txt))) (let ((txt " 0,0,0,0,168,169,0,0,0,0, 844,0,0,0,0,0,845,546,546,546, ")) (tilemap-tileset (parse-tilemap txt))) (load-tilemap "assets/level-0.tmx") (current-directory) ) ) ;; End tilemap module