;;; Copyright (C) 2025 Gene Pasquet ;;; ;;; This program is free software: you can redistribute it and/or modify ;;; it under the terms of the GNU General Public License as published by ;;; the Free Software Foundation, either version 3 of the License, or ;;; (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program. If not, see . (import utils [sub-points distance Direction]) ;; Define systems here (setv GRAVITY 5) (defclass GoalHit [Exception]) (defn entities-by-type [entities types] (gfor ent entities :if (in ent.type types) ent)) (defmacro defsystem [name pred #* body] `(defn ~name [entity entities] (when ~pred ~@body))) (defsystem apply-gravity (not entity.fixed) (.move entity #(0 GRAVITY))) (defsystem apply-collisions (not entity.fixed) (for [ent (gfor enti entities :if (!= enti.id entity.id) enti)] (when (.colliderect entity.rect ent.rect) (if (= ent.type "goal") (raise (GoalHit)) (let [collision-rect (.clip entity.rect ent.rect) move-x (get entity.total-move 0) move-y (get entity.total-move 1)] (when (!= move-x 0) (.move entity #((* (if (> move-x 0) -1 1) collision-rect.width) 0))) (when (!= move-y 0) (.move entity #(0 (* (if (> move-y 0) -1 1) collision-rect.height)))))) (.ground entity)))) (defsystem run-enemies (= entity.type "enemy") ;; If the player is on the tile next to the enemy, attack. (let [player (next (entities-by-type entities ["player"])) delta (sub-points entity.pos player.pos) dist (distance entity.pos player.pos) direction (.x-from-move Direction delta)] ;; If facing the player and within reach, attack) (when (and (= direction entity.facing) (< (get delta 1) 1) ;; Same level (< (abs (get delta 0)) 2) (not entity.attacking)) (.attack entity)) ;; If not facing the player, turn to face (when (and (< dist 5) (!= direction entity.facing)) (.move entity #((if (< (get delta 0) 0) -1 1) 0))) ))