`(kakko ,man)

Find a guide into tomorrow by taking lessons from the past

Lisp Game Programming 2 <Stage 11>

f:id:tomekame0126:20151015195902p:plain
Stage11では、左Shiftキーを押すと敵と敵の弾が全て破壊され、爆発するような関数を組み込むことにする。

以下のプログラムでは、bomb-managerクラスの作成と、shipが爆発中でなく且つボムが残っていて爆発中でない時に左Shiftキーを押すと、ボムが爆発してボムマークを1つ減らしている。

今後の予定としては、Stage12で衝突判定を組み込んでとりあえずの完成とし、作成したプログラムをすべて掲載することとしよう。
但し、全ての敵弾が一発一発発射されるため、ゲームとしては今一つなことから弾幕の設計を考えてみたい。でもどうやるんだろ?
何となく、ショットパターンの構造体を配列化するのが手っ取り早くできそうな気もするが、過去にLisp弾幕なんて作った例があるんだろうか?
探してみるけどどうだろ?(たぶん望み薄)

;; step11 <Set Bomb Key>
;; -----------------------------------------------------------------------------------------------
(define-class bomb-manager ()
  (bomb-list bomb-cnt bomb-flag bomb-number) nil)
; bomb-list    list of bomb       
; bomb-cnt     60 times waiting   
; bomb-flag    on (exploding) / off(not exploding)
; bomb-number  max 10

(defgeneric Set-bomb-key (ship bomb-manager keystate score))
(defmethod Set-bomb-key (ship bomb-manager keystate score)
  "bomb key push"
  (when (and (/= (state ship) 2)
             (/= (n-bomb score) 0)
             (eql (bomb-flag bomb-manager) nil)
             (eql (lshift keystate) t))
    (decf (n-bomb score) 1)                     ; decrement n-bomb    3 -> 0     
    (setf (bomb-flag bomb-manager) t            ; bomb-flag ON
          (lshift keystate) nil)))              ; reset lshift key

;; step11 <Set Bomb>
;; -----------------------------------------------------------------------------------------------
(defvar *rnd1*)
(defvar *rnd2*)

(defgeneric Set-bomb (bomb-manager enemy-manager))
(defmethod Set-bomb (bomb-manager enemy-manager)
  "set bomb"
  (when (eql (bomb-flag bomb-manager) t)          ; when bomb-flag is ON
    (when (and (= (mod (bomb-cnt bomb-manager) 15) 0)
               (> (bomb-cnt bomb-manager) 0))      
      (dotimes (i (bomb-number bomb-manager))
        (let ((bomb (make-instance 'entity :id 67 :width 64 :height 64 :state 1)))
	  (setf *rnd1* (random 256)
                *rnd2* (random 384))
          (setf (x bomb) (+ 160 *rnd1*)
                (y bomb) (+ 16  *rnd2*)) 
          (push bomb (bomb-list bomb-manager))))      
      (dolist (enemy (enemy-list enemy-manager))
        (when (or (= (state enemy) 1)               ; if enemy is alive
                  (= (state enemy) 2))              ; or enemy is damaged
          (setf (state enemy) 2
                (damage-cnt enemy) 0)
          (decf (life-cnt enemy) 1))))
    (decf (bomb-cnt bomb-manager) 1)              ; decrement bomb-cnt 60 -> 0
    (when (= (bomb-cnt bomb-manager) 0)           ; if bomb counter is 0 , reset 60
      (setf (bomb-cnt bomb-manager) 60            ; and set bomb flag nil 
            (bomb-flag bomb-manager) nil))))    
                                                      
;; step11 <Explode Bomb>
;; -----------------------------------------------------------------------------------------------
(defvar *bomb-explodes-flag* nil)

(defgeneric Explode-bomb (bomb-manager enemy-manager))
(defmethod Explode-bomb (bomb-manager enemy-manager)
  "bomb explosion while 15 times loop"
  (dolist (bomb (bomb-list bomb-manager))
     (incf (explode-cnt bomb) 1)      
      (when (eql *bomb-explodes-flag* nil)
        (setf *bomb-explodes-flag* t)             ; bomb explode sound on
        (Play-sample *bomb*))                     ; bomb explode sound                           
      (when (= (explode-cnt bomb) 15)             ; when bomb explode count is 15
        (setf (state bomb) 0                      ; set state of bomb  0
              *bomb-explodes-flag* nil)
        (dolist (enemy-shot (enemy-shot-list enemy-manager))
          (setf (state enemy-shot) 0)))))         ; set state of enemy-shot 0

;; step11 <Remove Explode Bomb>
;; -----------------------------------------------------------------------------------------------
(defgeneric Remove-explode-bomb (bomb-manager))
(defmethod Remove-explode-bomb (bomb-manager)
  "explode bomb remove from list"
  (setf (bomb-list bomb-manager) 
	(delete-if #'(lambda (bomb) (= (state bomb) 0)) (bomb-list bomb-manager))))

;; step11 <Draw Bomb>
;; -----------------------------------------------------------------------------------------------
(defgeneric Draw-bomb (bomb-manager))
(defmethod Draw-bomb (bomb-manager)
  (dolist (bomb (bomb-list bomb-manager))
    (when (= (state bomb) 1)
      (cond ((and (>= (explode-cnt bomb) 0)
                  (<  (explode-cnt bomb) 5))
              (setf (id bomb) 67))
            ((and (>= (explode-cnt bomb) 5) 
                  (<  (explode-cnt bomb) 10))
              (setf (id bomb) 68))
            ((and (>= (explode-cnt bomb) 10)
                  (<  (explode-cnt bomb) 15))          
              (setf (id bomb) 69)))
      (Draw bomb))))                                     ; draw  bomb