From 729f0b687b975e60f338831bcb0d59fad776f3e1 Mon Sep 17 00:00:00 2001 From: David Thompson Date: Sun, 12 Apr 2020 09:03:41 -0400 Subject: Day 2 progress. --- lisparuga/actor.scm | 35 +++++++++--- lisparuga/bullets.scm | 60 ++++++++++++-------- lisparuga/enemy.scm | 75 ++++++++++++++++++++++++- lisparuga/game.scm | 96 +++++++++++++++++++++++++++++-- lisparuga/kernel.scm | 6 +- lisparuga/node-2d.scm | 1 + lisparuga/player.scm | 152 +++++++++++++++++++++++++++++++++++++++++++------- 7 files changed, 364 insertions(+), 61 deletions(-) (limited to 'lisparuga') diff --git a/lisparuga/actor.scm b/lisparuga/actor.scm index c7caab2..5439e6b 100644 --- a/lisparuga/actor.scm +++ b/lisparuga/actor.scm @@ -28,6 +28,7 @@ #:use-module (lisparuga node) #:use-module (lisparuga node-2d) #:use-module (oop goops) + #:use-module (srfi srfi-1) #:use-module (srfi srfi-9) #:export (make-hitbox hitbox? @@ -43,6 +44,7 @@ velocity hitboxes world-hitboxes + collide on-collision bullet-field)) @@ -69,7 +71,10 @@ (make-rect 0.0 0.0 (rect-width r) (rect-height r))))) (define (sync-world-hitbox world-hitbox position) - (rect-move-vec2! (world-hitbox-rect world-hitbox) position)) + (let ((r (hitbox-rect (world-hitbox-parent world-hitbox))) + (wr (world-hitbox-rect world-hitbox))) + (set-rect-x! wr (+ (vec2-x position) (rect-x r))) + (set-rect-y! wr (+ (vec2-y position) (rect-y r))))) (define (world-hitbox-collision? a b) (if (world-hitbox? b) @@ -88,10 +93,18 @@ (world-hitboxes #:accessor world-hitboxes #:init-form '()) (bullet-field #:accessor bullet-field #:init-keyword #:bullet-field)) +(define (sync-hitboxes actor) + ;; Sync hitboxes to world coordinates. + (let ((pos (position actor))) + (for-each (lambda (world-hitbox) + (sync-world-hitbox world-hitbox pos)) + (world-hitboxes actor)))) + (define-method (initialize (actor ) initargs) (next-method) (set! (world-hitboxes actor) - (map make-world-hitbox (hitboxes actor)))) + (map make-world-hitbox (hitboxes actor))) + (sync-hitboxes actor)) (define-method (update (actor ) dt) (let ((v (velocity actor))) @@ -99,15 +112,21 @@ (= (vec2-y v) 0.0)) ;; Move by current velocity. (vec2-add! (position actor) v) - ;; Sync hitboxes to world coordinates. - (let ((pos (position actor))) - (for-each (lambda (world-hitbox) - (sync-world-hitbox world-hitbox pos)) - (world-hitboxes actor))) + (sync-hitboxes actor) ;; Mark for matrix updates. (dirty! actor)))) +(define-method (collide (actor ) (other-actor )) + (any (lambda (wh) + (any (lambda (other-wh) + (and (world-hitbox-collision? wh other-wh) + (on-collision actor other-actor + (world-hitbox-parent wh) + (world-hitbox-parent other-wh)))) + (world-hitboxes other-actor))) + (world-hitboxes actor))) + ;; Actor-actor collision event. (define-method (on-collision (actor ) (other-actor ) hitbox other-hitbox) - #t) + #f) diff --git a/lisparuga/bullets.scm b/lisparuga/bullets.scm index e241694..6645f0d 100644 --- a/lisparuga/bullets.scm +++ b/lisparuga/bullets.scm @@ -39,7 +39,7 @@ bullet-hitbox-rect bullet-tile ikaruga-bullet - ikaruga-missle + ikaruga-missile small-dot medium-dot large-dot @@ -48,7 +48,6 @@ spawn-bullet - collision? size capacity texture-atlas)) @@ -68,11 +67,11 @@ (tile-black bullet-tile-black)) (define ikaruga-bullet - (make-bullet 'ikaruga (make-rect 0.0 0.0 0.0 0.0) 0 1)) + (make-bullet 'ikaruga (make-rect -3.0 -1.0 6.0 10.0) 0 1)) (define ikaruga-missile - (make-bullet 'ikaruga-missile (make-rect 0.0 0.0 0.0 0.0) 0 1)) + (make-bullet 'ikaruga-missile (make-rect -3.0 -1.0 6.0 10.0) 4 5)) (define small-dot - (make-bullet 'small-dot (make-rect 0.0 0.0 0.0 0.0) 0 1)) + (make-bullet 'small-dot (make-rect -1.0 -1.0 2.0 2.0) 0 1)) (define medium-dot (make-bullet 'medium-dot (make-rect 0.0 0.0 0.0 0.0) 0 1)) (define large-dot @@ -98,6 +97,7 @@ (positions #:accessor positions) (velocities #:accessor velocities) (hitboxes #:accessor hitboxes) + (procs #:accessor procs) (texture-atlas #:accessor texture-atlas #:init-keyword #:texture-atlas) (scratch-rect #:getter scratch-rect #:init-form (make-rect 0.0 0.0 0.0 0.0))) @@ -115,7 +115,8 @@ (set! (polarities bullets) (make-vector capacity)) (set! (positions bullets) (seed-vector (lambda () #v(0.0 0.0)))) (set! (velocities bullets) (seed-vector (lambda () #v(0.0 0.0)))) - (set! (hitboxes bullets) (seed-vector (lambda () (make-rect 0.0 0.0 0.0 0.0)))))) + (set! (hitboxes bullets) (seed-vector (lambda () (make-rect 0.0 0.0 0.0 0.0)))) + (set! (procs bullets) (make-vector capacity)))) (define-method (spawn-bullet (bullets ) id polarity x y dx dy) (let* ((i (size bullets)) @@ -128,22 +129,29 @@ (vector-set! (polarities bullets) i polarity) (set-vec2! p x y) (set-vec2! v dx dy) - (set-rect-x! h (rect-x r)) - (set-rect-y! h (rect-y r)) + (set-rect-x! h (+ x (rect-x r))) + (set-rect-y! h (+ y (rect-y r))) (set-rect-width! h (rect-width r)) - (set-rect-height! h (rect-height r)))) + (set-rect-height! h (rect-height r)) + (vector-set! (procs bullets) i #f))) + +(define-method (spawn-bullet (bullets ) id polarity x y dx dy proc) + (spawn-bullet bullets id polarity x y dx dy) + (vector-set! (procs bullets) (- (size bullets) 1) proc)) (define-method (move-bullet (bullets ) from to) (let ((ids (ids bullets)) (polarities (polarities bullets)) (positions (positions bullets)) (velocities (velocities bullets)) - (hitboxes (hitboxes bullets))) + (hitboxes (hitboxes bullets)) + (procs (procs bullets))) (vector-set! ids to (vector-ref ids from)) (vector-set! polarities to (vector-ref polarities from)) (vec2-copy! (vector-ref positions from) (vector-ref positions to)) (vec2-copy! (vector-ref velocities from) (vector-ref velocities to)) - (rect-copy! (vector-ref hitboxes from) (vector-ref hitboxes to)))) + (rect-copy! (vector-ref hitboxes from) (vector-ref hitboxes to)) + (vector-set! procs to (vector-ref procs from)))) (define-method (kill-bullet (bullets ) i) (let ((new-size (- (size bullets) 1))) @@ -158,6 +166,7 @@ (positions (positions bullets)) (velocities (velocities bullets)) (hitboxes (hitboxes bullets)) + (procs (procs bullets)) ;; Delete bullets that go too far off the screen. (min-x -32.0) (min-y -32.0) @@ -171,7 +180,9 @@ (when (< i l) (let ((p (vector-ref positions i)) (v (vector-ref velocities i)) - (h (vector-ref hitboxes i))) + (h (vector-ref hitboxes i)) + (proc (vector-ref procs i))) + (and (procedure? proc) (proc p v)) (vec2-add! p v) ;; Remove bullets that go out of bounds of the play area. (if (or (< (vec2-x p) min-x) @@ -198,17 +209,20 @@ (polarities (polarities bullets)) (hitboxes (hitboxes bullets))) (let loop ((i 0)) - (when (< i l) - (let* ((id (vector-ref ids i)) - (h (vector-ref hitboxes i)) - (wh (find (lambda (wh) - (world-hitbox-collision? wh h)) - (world-hitboxes actor)))) - (if (and wh - (on-collision actor id (vector-ref polarities i) - (world-hitbox-parent wh))) - (kill-bullet bullets i) - (loop (+ i 1)))))))) + (if (< i l) + (let* ((id (vector-ref ids i)) + (h (vector-ref hitboxes i)) + (collided? (find (lambda (wh) + (and (world-hitbox-collision? wh h) + (on-collision actor id (vector-ref polarities i) + (world-hitbox-parent wh)))) + (world-hitboxes actor)))) + (if collided? + (begin + (kill-bullet bullets i) + #t) + (loop (+ i 1)))) + #f)))) (define %identity-matrix (make-identity-matrix4)) diff --git a/lisparuga/enemy.scm b/lisparuga/enemy.scm index 5ecba62..0589d16 100644 --- a/lisparuga/enemy.scm +++ b/lisparuga/enemy.scm @@ -21,6 +21,7 @@ ;;; Code: (define-module (lisparuga enemy) + #:use-module (chickadee math) #:use-module (chickadee math rect) #:use-module (chickadee math vector) #:use-module (chickadee scripting) @@ -36,6 +37,8 @@ health points parting-shots + dead? + fire-parting-shots-maybe make-utatsugumi)) @@ -46,7 +49,68 @@ (define-class () (health #:accessor health #:init-keyword #:health) (points #:getter points #:init-keyword #:points) - (parting-shots #:getter parting-shots #:init-keyword #:parting-shots)) + (parting-shots #:getter parting-shots #:init-keyword #:parting-shots) + (fire-parting-shots? #:accessor fire-parting-shots? #:init-form #f)) + +(define-method (on-kill (enemy )) + #t) + +(define-method (damage (enemy ) x) + (set! (health enemy) (max (- (health enemy) x) 0))) + +(define-method (dead? (enemy )) + (zero? (health enemy))) + +(define (fire-parting-shots-maybe enemy player) + (when (fire-parting-shots? enemy) + (let* ((n (parting-shots enemy)) + (ep (position enemy)) + (pp (position player)) + (angle-to-player + (atan (- (vec2-y pp) (vec2-y ep)) + (- (vec2-x pp) (vec2-x ep))))) + (let loop ((i 0)) + (when (< i n) + (let ((theta (+ angle-to-player + (- (* (random:uniform) (/ pi 4.0)) + (/ pi 8.0))))) + (spawn-bullet (bullet-field enemy) + small-dot + (polarity enemy) + (+ (vec2-x ep) + (- (* (random:uniform) 16.0) + 8.0)) + (+ (vec2-y ep) + (- (* (random:uniform) 16.0) + 8.0)) + (* (cos theta) 4.0) + (* (sin theta) 4.0))) + (loop (+ i 1))))))) + +(define-method (on-collision (enemy ) bullet bullet-polarity hitbox) + ;; TODO: Distinguish between normal play bullets and homing shots + ;; that do more damage. + ;; + ;; Same polarity = 1 point of damage + ;; Opposite polarity = 2 points of damage + (let ((same-polarity? (eq? bullet-polarity (polarity enemy)))) + (damage enemy (if same-polarity? 1 2)) + (when (and same-polarity? (dead? enemy)) + (set! (fire-parting-shots? enemy) #t))) + #t) + +(define %enemy-tiles + ;; 0: Utatsugumi - white + `((0.0 0.0 24.0 24.0) + ;; 1: Utatsugumi - black + (24.0 0.0 24.0 24.0))) + +(define (load-enemy-atlas file-name) + (let ((texture (load-image file-name))) + (list->texture-atlas texture %enemy-tiles))) + +(define-asset enemy-atlas + (load-enemy-atlas (scope-asset "images/enemies.png"))) ;;; @@ -55,6 +119,13 @@ (define-class ()) +(define-method (on-boot (utatsugumi )) + (attach-to utatsugumi + (make + #:atlas enemy-atlas + #:index (if (eq? 'white (polarity utatsugumi)) 0 1) + #:origin (vec2 12.0 12.0)))) + (define (make-utatsugumi polarity x y) (make #:name (gensym "utatsugumi-") @@ -62,4 +133,6 @@ #:points 20 #:parting-shots 5 #:polarity polarity + #:hitboxes + (list (make-hitbox 'utatsugumi (make-rect -10.0 -10.0 20.0 20.0))) #:position (vec2 x y))) diff --git a/lisparuga/game.scm b/lisparuga/game.scm index edd97fc..5b14edd 100644 --- a/lisparuga/game.scm +++ b/lisparuga/game.scm @@ -26,9 +26,13 @@ #:use-module (chickadee math vector) #:use-module (chickadee render color) #:use-module (chickadee render texture) + #:use-module (chickadee scripting) + #:use-module (ice-9 format) + #:use-module (lisparuga actor) #:use-module (lisparuga asset) #:use-module (lisparuga bullets) #:use-module (lisparuga config) + #:use-module (lisparuga enemy) #:use-module (lisparuga node) #:use-module (lisparuga node-2d) #:use-module (lisparuga player) @@ -43,28 +47,109 @@ (define-asset clouds (load-image (scope-asset "images/clouds.png"))) (define-asset player-bullet-atlas (load-tile-atlas (scope-asset "images/player-bullets.png") 16 16)) +(define-asset enemy-bullet-atlas + (load-tile-atlas (scope-asset "images/enemy-bullets.png") 24 24)) ;; nodes needed: -;; enemies -;; enemy bullets ;; scrolling background (define-class ()) (define-method (on-boot (game )) (let* ((player-bullets (make + #:name 'player-bullets + #:rank 2 #:capacity 500 #:texture-atlas player-bullet-atlas)) (player (make-player player-bullets)) (enemy-bullets (make + #:name 'enemy-bullets + #:rank 4 #:capacity 1000 - #:texture-atlas player-bullet-atlas))) + #:texture-atlas enemy-bullet-atlas)) + (ui (make + #:name 'ui + #:rank 999))) + (set! (rank player) 1) (attach-to game (make #:name 'clouds + #:rank 0 #:texture clouds) player player-bullets - enemy-bullets))) + (make + #:name 'enemies + #:rank 3) + enemy-bullets + ui) + ;; Setup UI elements + (attach-to ui + (make