1
;; -*- coding: utf-8; mode: scheme -*-
3
;; breakout.scm - Breakout
5
;; Copyright (c) 2007 KOGURO, Naoki (naoki@koguro.net)
6
;; All rights reserved.
8
;; Redistribution and use in source and binary forms, with or without
9
;; modification, are permitted provided that the following conditions
12
;; 1. Redistributions of source code must retain the above copyright
13
;; notice, this list of conditions and the following disclaimer.
14
;; 2. Redistributions in binary form must reproduce the above copyright
15
;; notice, this list of conditions and the following disclaimer in the
16
;; documentation and/or other materials provided with the distribution.
17
;; 3. Neither the name of the authors nor the names of its contributors
18
;; may be used to endorse or promote products derived from this
19
;; software without specific prior written permission.
21
;; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22
;; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23
;; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24
;; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25
;; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26
;; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
27
;; TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28
;; PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29
;; LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30
;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31
;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40
(c-load '("SDL.h" "SDL_mixer.h" "stdio.h" "stdlib.h" "sdl_helper.c")
41
:cppflags-cmd "sdl-config --cflags"
42
:libs-cmd "sdl-config --libs; echo '-lSDL_mixer'"
43
:import (list (lambda (header sym)
44
(#/\/SDL\/.*\.h$/ header))
47
:compiled-lib "sdllib")
50
(define-constant *screen-width* 640)
51
(define-constant *screen-height* 480)
52
(define-constant *screen-depth* 8)
55
(define *ball-rect* #f)
56
;; vx and vy must be a multiple of *unit*.
59
(define *ball-count* 0)
60
(define-constant *ball-size* *unit*)
62
(define *paddle-rect* #f)
63
(define *paddle-width* (* 8 *unit*))
64
(define *paddle-vx* 0)
66
(define *block-list* '())
67
(define *block-start-x* 0)
68
(define *block-start-y* 0)
69
(define *block-end-x* 0)
70
(define *block-end-y* 0)
72
(define-constant *block-width* (* 6 *unit*))
73
(define-constant *block-height* (* 3 *unit*))
76
(define *tick-threshold* 20)
78
(define *bounce-sound* #f)
79
(define *shoot-sound* #f)
82
(SDL_Init (logior SDL_INIT_VIDEO SDL_INIT_AUDIO))
83
(set! *screen* (SDL_SetVideoMode *screen-width* *screen-height*
87
(SDL_WM_SetCaption "Breakout" NULL)
88
(set! *paddle-rect* (make <SDL_Rect>))
89
(set! (ref *paddle-rect* 'w) *paddle-width*)
90
(set! (ref *paddle-rect* 'h) *unit*)
92
(Mix_OpenAudio 44100 AUDIO_S16SYS 2 1024)
93
(set! *bounce-sound* (Mix_LoadWAV "cursor5.wav"))
94
(set! *shoot-sound* (Mix_LoadWAV "cursor6.wav"))
98
(set! (ref *paddle-rect* 'x) (- (/ *screen-width* 2)
99
(/ (ref *paddle-rect* 'w) 2)))
100
(set! (ref *paddle-rect* 'y) (- *screen-height* (* 3 *unit*)))
101
(set! *ball-count* 2)
104
(define (make-block x y color)
105
(let ((rect (make <SDL_Rect>)))
106
(set! (ref rect 'x) (+ x 1))
107
(set! (ref rect 'y) (+ y 1))
108
(set! (ref rect 'w) (- *block-width* 2))
109
(set! (ref rect 'h) (- *block-height* 2))
110
(vector (list x y (+ x *block-width*) (+ y *block-height*))
114
(define (block-vertical-reflect? block x y vx)
115
(receive (sx sy ex ey) (apply values (vector-ref block 0))
117
(or (and (= x sx) (< 0 vx))
118
(and (= x ex) (< vx 0))))))
120
(define (block-horizontal-reflect? block x y vy)
121
(receive (sx sy ex ey) (apply values (vector-ref block 0))
123
(or (and (= y sy) (< 0 vy))
124
(and (= y ey) (< vy 0))))))
126
(define (block-hit? block x y)
127
(receive (sx sy ex ey) (apply values (vector-ref block 0))
128
(and (<= sx x ex) (<= sy y ey))))
130
(define (make-blocks)
131
(do ((block-list '())
132
(level 0 (+ level 1))
133
(colors '(#o700 #o770 #o373 #o077 #o007) (cdr colors))
134
(y (* 7 *unit*) (+ y *block-height*)))
136
(set! *block-list* block-list))
137
(do ((x (* 1 *unit*) (+ x *block-width*)))
138
((<= *screen-width* (+ x *block-width*)))
139
(push! block-list (make-block x y (car colors)))))
140
(set! *block-start-x* *screen-width*)
141
(set! *block-start-y* *screen-height*)
142
(set! *block-end-x* 0)
143
(set! *block-end-y* 0)
144
(for-each (lambda (block)
145
(receive (sx sy ex ey) (apply values (vector-ref block 0))
146
(when (< sx *block-start-x*)
147
(set! *block-start-x* sx))
148
(when (< sy *block-start-y*)
149
(set! *block-start-y* sy))
150
(when (< *block-end-x* ex)
151
(set! *block-end-x* ex))
152
(when (< *block-end-y* ey)
153
(set! *block-end-y* ey))))
161
(let ((rect (make <SDL_Rect>)))
162
(set! (ref rect 'x) 0)
163
(set! (ref rect 'y) 0)
164
(set! (ref rect 'w) *screen-width*)
165
(set! (ref rect 'h) *screen-height*)
167
(SDL_FillRect *screen* (ptr rect) 0))))
169
(define (draw-paddle)
170
(SDL_FillRect *screen* (ptr *paddle-rect* ) #o777))
172
(define (move-paddle-left)
173
(set! *paddle-vx* (- *unit*)))
175
(define (move-paddle-right)
176
(set! *paddle-vx* *unit*))
178
(define (move-paddle)
179
(let ((new-x (+ (ref *paddle-rect* 'x) *paddle-vx*))
180
(w (ref *paddle-rect* 'w)))
183
(when (< (- *screen-width* w) new-x)
184
(set! new-x (- *screen-width* w)))
185
(set! (ref *paddle-rect* 'x) new-x)))
187
(define (stop-paddle)
188
(set! *paddle-vx* 0))
192
(SDL_FillRect *screen* (ptr *ball-rect*) #o777)))
197
(set! *ball-vx* (- *ball-vx*))
200
(set! *ball-vy* (- *ball-vy*))
203
(let ((new-x (+ (ref *ball-rect* 'x) *ball-vx*))
204
(new-y (+ (ref *ball-rect* 'y) *ball-vy*))
205
(paddle-x (ref *paddle-rect* 'x))
206
(paddle-y (ref *paddle-rect* 'y))
207
(paddle-w (ref *paddle-rect* 'w))
208
(paddle-h (ref *paddle-rect* 'h))
209
(w (ref *ball-rect* 'w))
210
(h (ref *ball-rect* 'h)))
213
(set! new-x (- new-x)))
214
(when (< (- *screen-width* w) new-x)
216
(set! new-x (- (* 2 (- *screen-width* w)) new-x)))
220
(when (and (<= paddle-y new-y (+ paddle-y paddle-h))
221
(<= paddle-x new-x (+ paddle-x paddle-w)))
223
(when (or (and (= paddle-x new-x)
225
(and (= (+ paddle-x paddle-w (- *unit*)) new-x)
228
(set! new-y (- paddle-y h)))
229
(when (< (- *screen-height* h) new-y)
231
(set! *ball-rect* #f))
232
(when (and (<= *block-start-x* new-x *block-end-x*)
233
(<= *block-start-x* new-y *block-end-y*))
234
(do ((block-list *block-list* (cdr block-list))
235
(result '() (cons (car block-list) result)))
236
((or (null? block-list)
237
(block-hit? (car block-list) new-x new-y))
238
(unless (null? block-list)
239
(when (block-vertical-reflect? (car block-list) new-x new-y
242
(when (block-horizontal-reflect? (car block-list) new-x new-y
245
(set! *block-list* (append result (cdr block-list)))))))
247
(set! (ref *ball-rect* 'x) new-x)
248
(set! (ref *ball-rect* 'y) new-y))
250
(Mix_PlayChannel -1 *bounce-sound* 0))))))
254
(let ((paddle-x (ref *paddle-rect* 'x))
255
(paddle-y (ref *paddle-rect* 'y))
256
(paddle-w (ref *paddle-rect* 'w))
257
(paddle-h (ref *paddle-rect* 'h)))
258
(set! *ball-rect* (make <SDL_Rect>))
259
(set! (ref *ball-rect* 'w) *ball-size*)
260
(set! (ref *ball-rect* 'h) *ball-size*)
261
(set! (ref *ball-rect* 'x) (+ paddle-x (/ paddle-w 2)))
262
(set! (ref *ball-rect* 'y) paddle-y)
263
(set! *ball-vx* (* (- (* 2 (random-integer 2)) 1) *unit*))
264
(set! *ball-vy* (- *unit*))
265
(format #t "ball: ~a~%" *ball-count*)
266
(Mix_PlayChannel -1 *shoot-sound* 0))))
268
(define (draw-blocks)
269
(for-each (lambda (block)
270
(SDL_FillRect *screen*
271
(ptr (vector-ref block 1))
272
(vector-ref block 2)))
275
(define (poll-event event)
276
(SDL_PollEvent (ptr event))
277
(unless (< 0 (SDL_PollEvent (ptr event)))
278
(let ((type (ref event 'type)))
282
((eq? type SDL_KEYDOWN)
283
(case (ref* event 'key 'keysym 'sym)
300
(define (sdl-main argc argv)
302
(let ((event (make <SDL_Event>)))
303
(do ((continue? (poll-event event) (poll-event event)))
307
(let ((delta (- (SDL_GetTicks) *tick*)))
308
(when (< *tick-threshold* delta)
310
(set! *tick* (SDL_GetTicks))))
318
(print "GAME OVER!!")
320
((null? *block-list*)
321
(set! *ball-rect* #f)
327
(run_sdl_main (length args) args sdl-main))