Lisp Game Programming 2 <Stage 11>
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