Question

Some background, I'm making Space Invaders as a project in a CS class. Currently I'm working on making the player ship shoot projectiles, not worrying about collisions, just spawning projectiles.

(define projectile%
(class object%
(init-field [image (make-bitmap 10 10)]
            [x 100]
            [y 100]
            [speed 1])
(define/public (get-image) image)
(define/private (move-up)
  (set! y (- y speed)))
(define/public (render dc)
  (let ((w (send image get-width))
        (h (send image get-height)))
    (move-up)
    (send dc translate (+ x (/ w 2)) (+ y (/ h 2)))
    (send dc draw-bitmap image (- (/ w 2)) (- (/ h 2)))
    (send dc translate (- (+ x (/ w 2))) (- (+ y (/ h 2))))))
(super-new)))



(define player-ship%
  (class object%
    (init-field [image (make-bitmap 30 25)]
            [x 400]
            [y 300]
            [speed 3])
(define/public (get-image) image)
(define/public (get-x) x)
(define/public (get-y) y)
(define/private (shoot)  
  ;Spawning a projectile would go here
(define/public (render dc)
  (let ((w (send image get-width))
        (h (send image get-height)))
    (send dc translate (+ x (/ w 2)) (+ y (/ h 2)))
    (send dc draw-bitmap image (- (/ w 2)) (- (/ h 2)))
    (send dc translate (- (+ x (/ w 2))) (- (+ y (/ h 2))))))
(define/public (key-down key-code)
  (cond ((equal? key-code 'left) (move-left))
        ((equal? key-code 'right) (move-right))
        ((equal? key-code 'up) (shoot))))
(super-new)))

Those are the two relevant classes, some failed code for spawning a projectile removed.

Some code for how I'm drawing the window and stuff:

(define *my-game-canvas*
  (new game-canvas%
       [parent *game-window*]
       [paint-callback (lambda (canvas dc)
                         (begin
                           (send *my-ship* render dc)
                           (send *ship-projectile* render dc)))]
       [keyboard-handler (lambda (key-event)
                           (let ((key-code (send key-event get-key-code)))
                             (if (not (equal? key-code 'release))
                                 (send *my-ship* key-down key-code))))]))
(define *my-timer* (new timer%
                        [notify-callback (lambda ()
                                           (send *my-game-canvas* refresh))]))

(make-ship-projectile (send *ship-projectile* get-image))
;creating a projectile just seeing whether they work or not
(make-ship (send *my-ship* get-image))

The make-ship and make-ship-projectile functions work as follows:

(define (make-ship-projectile bitmap-target)
 (let ((dc (new bitmap-dc% [bitmap bitmap-target])))
    (send dc set-brush (make-object brush% "black" 'solid))
    (send dc draw-ellipse 0 0 10 10)))

The problem arises when I try to create a new projectile with the shoot method in player-ship%, it simply doesn't work. I'm currently under the assumption that it doesn't work due to the new projectile not being in my-game-canvas's paint-callback, however, I do not know how to update that attribute. Am I approaching it from the wrong direction?

Was it helpful?

Solution

Yes, if the drawing of the projectile is not triggered from paint-callback (or another function/method called from it), it will not be displayed in the canvas when the canvas is refreshed.

One possibility is to have a list of existing projectiles (possibly an attribute in player-ship%), and paint-callback should trigger (possibly via player-ship%'s render method, or via a different method in player-ship% like render-projectiles that is called from the paint-callback) the display of all these projectiles in the canvas. When a new projectile is shot from the ship, it should be added to the list of existing projectiles and when the projectile hits something or escapes the board, it should be removed from this list.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top