(libload "libc/constants") (libload "sdl/libsdl") (setq pi/180 (/ 3.1415927 180)) ;; a simple Lunar Lander game in less than 60 lines of Lush (de lander () ;; initialize the SDL subsystem. DONT FORGET THIS!!! (sdl-initialize) (let* ((scr (new sdl-screen 640 480 "Lander")) ; open screen (bgd (new sdl-sprite scr 0)) ; create background sprite (ship (new sdl-sprite scr 1)) ; create lem sprite (flame (new sdl-sprite scr 1)) ; create flame sprite (shadow (new sdl-sprite scr 3)) ; create shadow sprite ;; set position, velocity, acceleration of ship (x 200) (y 100) (vx 4) (vy 0) (ax 0) (ay 0) ;; angle of ship (theta 0) ;; set mass, inverse mass, and deltat of ship (mass 1) (mass-inv (/ 1 mass)) (deltat 0.01) (main-thrust 400) ; set main engine thrust (grav 200) ; set gravity coefficient in pixels/s/s (stop ()) (event (new sdl-event)) (xyk (int-matrix 3)) (ground 360)) (==> bgd load-frame "moon.png" 0 0 0) (==> bgd move 0 0) ;; put the handle at the center of the sprite (40,35) (==> ship load-frame "lem.png" 0 40 35) (==> flame load-frame "lem-flame.png" 0 40 35) (==> shadow load-frame "lem-shadow.png" 0 40 -6) ;; fill up frames with rotated lems (let ((i 1)) ;; make an image every 10 degrees from 10 to 350 (for (angle 10 350 10) ;; take frame 0, rotate by angle, scale by 1, ;; and copy into frame i (==> ship rotscale-frame 0 i angle 1) ;; same for flame (==> flame rotscale-frame 0 i angle 1) (incr i))) (while (not stop) (==> scr clear) ; fill image with black (==> bgd draw) ; draw moon ground (==> event get-arrows xyk) ; read keyboard (when (= (xyk 2) @@SDLK_q) (setq stop t)) ; stop when q is pressed ;; update the angle from the left-right arrow keys (setq theta (+ theta (xyk 0))) ;; bring the angle back to the 0-360 interval (while (>= theta 36) (setq theta (- theta 36))) (while (< theta 0) (setq theta (+ theta 36))) ;; set frame of ship and flame to one matching the angle (==> ship set-frame (int theta)) (==> flame set-frame (int theta)) ;; compute x acceleration (setq ax (* mass-inv main-thrust (xyk 1) (sin (* pi/180 -10 theta)))) ;; compute y acceleration (setq ay (+ grav (* mass-inv main-thrust (xyk 1) (cos (* pi/180 10 theta))))) (setq vx (+ vx (* ax deltat))) ; update velocity (setq vy (+ vy (* ay deltat))) ; update velocity (setq x (+ x (* vx deltat))) ; update position (setq y (+ y (* vy deltat))) ; update position (when (< x -40) (setq x (+ 640 (- x -40)))) ; wrap around left side (when (> x 680) (setq x (+ -40 (- x 640)))) ; wrap around right side (when (> y ground) ; bounce on ground (setq vy (* -0.5 vy)) (setq vx (* 0.25 vx)) (setq theta 0) (setq y ground)) (==> shadow move x 360) ; move shadow sprite to position (==> flame move x y) ; move flame sprite to position (==> ship move x y) ; move ship sprite to position ;; now draw sprites in the right order, bottom sprite first (==> shadow draw) ; draw shadow (when (<> 0 (xyk 1)) (==> flame draw)) ; draw flame if engine is on (==> ship draw) ; draw ship (==> scr flip) ; flip screens (setq deltat :scr:deltat)))) ; update deltat to time between screen flips