foss-mmo/modules/game/level.scm

137 lines
5.5 KiB
Scheme
Raw Normal View History

2024-05-26 12:52:03 -04:00
;;; Copyright (C) 2024 David Thompson <dave@spritely.institute>
;;;
;;; Licensed under the Apache License, Version 2.0 (the "License");
;;; you may not use this file except in compliance with the License.
;;; You may obtain a copy of the License at
;;;
;;; http://www.apache.org/licenses/LICENSE-2.0
;;;
;;; Unless required by applicable law or agreed to in writing, software
;;; distributed under the License is distributed on an "AS IS" BASIS,
;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
;;; See the License for the specific language governing permissions and
;;; limitations under the License.
(define-module (game level)
#:use-module (game actors)
#:use-module (goblins core)
#:use-module (hoot bytevectors)
#:use-module (ice-9 match)
2024-05-22 14:22:27 -04:00
#:use-module (math vector)
#:use-module (srfi srfi-9)
2024-05-22 14:22:27 -04:00
#:export (tile-width
tile-height
<level-tile>
level-tile?
level-tile-position
level-tile-id
make-level
level?
level-background
level-actor
level-player))
2024-05-22 14:22:27 -04:00
(define tile-width 16.0)
(define tile-height 16.0)
(define-record-type <level-tile>
(make-level-tile position id)
level-tile?
(position level-tile-position)
(id level-tile-id))
;; Client-side rendering info coupled with level actor that contains
;; game state.
(define-record-type <level>
(%make-level background actor player)
level?
(background level-background)
(actor level-actor)
(player level-player))
(define (make-level width height background objects collected-gem?)
(let ((level* (spawn ^level width height))
(background* (make-vector (* width height)))
(direction->symbol
(match-lambda
(1 'right)
(2 'left)
(3 'up)
(4 'down))))
2024-05-22 14:22:27 -04:00
;; Unpack background tile data.
(let y-loop ((y 0))
(when (< y height)
(let x-loop ((x 0))
(when (< x width)
(let* ((i (+ (* y width) x))
(pos (vec2 (* x tile-width) (* y tile-height)))
(id (case (bytevector-u16-native-ref background (* i 2))
((120) 81)
((121) 82)
((122) 85)
((123) 105)
(else => (lambda (v) v))))
2024-05-22 14:22:27 -04:00
(tile (make-level-tile pos id)))
(vector-set! background* i tile))
(x-loop (1+ x))))
(y-loop (1+ y))))
;; Unpack object data and spawn objects, making special
;; note of the player.
(let lp ((i 0) (player #f))
2024-05-22 14:22:27 -04:00
(if (< i (bytevector-length objects))
(let* ((x (bytevector-u8-ref objects i))
2024-05-22 10:35:11 -04:00
(y (bytevector-u8-ref objects (+ i 1)))
(id (bytevector-u8-ref objects (+ i 2)))
(obj (match id
(1 (spawn ^wall x y 'inert))
2024-05-22 10:35:11 -04:00
(2 (spawn ^wall x y 'copper))
(3 (spawn ^player x y))
(4 (spawn ^exit x y))
(5 (spawn ^block x y 'copper))
(6 (spawn ^block x y 'crate))
2024-05-23 16:28:53 -04:00
(7 (spawn ^clock-emitter x y
(bytevector-u8-ref objects (+ i 3))))
2024-05-22 10:35:11 -04:00
(8 (let ((target-x (bytevector-u8-ref objects (+ i 3)))
(target-y (bytevector-u8-ref objects (+ i 4))))
2024-05-22 10:35:11 -04:00
(spawn ^floor-switch x y target-x target-y)))
(9 (spawn ^gem x y collected-gem?))
2024-05-22 10:35:11 -04:00
(10 (spawn ^gate x y))
(11 (spawn ^and-gate x y
(direction->symbol
(bytevector-u8-ref objects (+ i 3)))))
2024-05-22 10:35:11 -04:00
(12 (let ((target-x (bytevector-u8-ref objects (+ i 3)))
(target-y (bytevector-u8-ref objects (+ i 4))))
(spawn ^electric-switch x y target-x target-y)))
(13 (spawn ^xor-gate x y
(direction->symbol
(bytevector-u8-ref objects (+ i 3)))))
2024-05-22 12:35:56 -04:00
(14 (let ((target-x (bytevector-u8-ref objects (+ i 3)))
(target-y (bytevector-u8-ref objects (+ i 4))))
(spawn ^electron-warp x y target-x target-y)))
(15 (spawn ^or-gate x y
(direction->symbol
(bytevector-u8-ref objects (+ i 3)))))
2024-05-23 16:28:53 -04:00
(16 (spawn ^switched-emitter x y
(bytevector-u8-ref objects (+ i 3))))
2024-05-24 12:46:15 -04:00
(17 (spawn ^bomb x y))
(18 (spawn ^brick x y))
2024-05-22 10:35:11 -04:00
(id (error "invalid level object" id))))
(i* (+ i (match id
2024-05-22 12:35:56 -04:00
;; floor-switch
;; electric-switch
;; electron-warp
((or 8 12 14) 5)
2024-05-23 16:28:53 -04:00
;; clock-emitter
;; logic gates
2024-05-23 16:28:53 -04:00
;; switched-emitter
((or 7 11 13 15 16) 4)
2024-05-22 10:35:11 -04:00
(_ 3)))))
(when obj
($ level* 'add-object obj))
2024-05-22 14:22:27 -04:00
(if (= id 3) ; player-spawn
(lp i* obj)
(lp i* player)))
2024-05-22 14:22:27 -04:00
(%make-level background* level* player)))))