ผลต่างระหว่างรุ่นของ "Prg2/space (applying design patterns)"

จาก Theory Wiki
ไปยังการนำทาง ไปยังการค้นหา
แถว 12: แถว 12:
 
* SpaceGame
 
* SpaceGame
 
* Ship (in <tt>elements.py</tt>)
 
* Ship (in <tt>elements.py</tt>)
* Bullet (in <tt>elements.py</tt>)
+
* Bullet and Enemy (in <tt>elements.py</tt>)
* Enemy (in <tt>elements.py</tt>)
 
 
* Bomb
 
* Bomb
  
แถว 87: แถว 86:
  
 
=== Ship ===
 
=== Ship ===
 +
 +
'''Ship''' (code in <tt>elements.py</tt>) maintains ship movement.  It cruises forward with constant speed.  The user can only change the ship's direction by turning left and right.  It also generate bullets with method <tt>fire</tt>:
 +
 +
<syntaxhighlight lang="python">
 +
    def fire(self):
 +
        if self.app.bullet_count() >= MAX_NUM_BULLETS:
 +
            return
 +
 +
        dx,dy = direction_to_dxdy(self.direction)
 +
 +
        bullet = Bullet(self.app, self.x, self.y, dx * BULLET_BASE_SPEED, dy * BULLET_BASE_SPEED)
 +
 +
        self.app.add_bullet(bullet)
 +
</syntaxhighlight>
 +
 +
This code leaves rooms for more creativity in creating bullets.
 +
  
 
=== Bullet and Enemy ===
 
=== Bullet and Enemy ===

รุ่นแก้ไขเมื่อ 23:01, 24 มีนาคม 2564

This is part of Programming 2 2563

Overview

In this assignment, you will apply design patterns to the provided Space Fighter code. In this game you can turn the ship with Left and Right keys. You can fire bullets with Spacebar and applying bombs with the Z key. You have 30 bullets at a time and the bomb needs cool-down period (to recharge its power to 100%).

Prg2-space-fighter.png

Understanding the current code

There are 5 main classes:

  • SpaceGame
  • Ship (in elements.py)
  • Bullet and Enemy (in elements.py)
  • Bomb

Changes in gamelib

Since we will have a lot of sprites flying around, it would cause the game huge delays if we keep out-of-scene sprites in the game. We add attribute to_be_deleted so that the sprite or the game app could signify the game loop that a sprite can be discarded and method delete to perform the actual deletion from the canvas. We also provide methods for stoping the game stop_animation and resuming the game resume_animation. Method animate becomes:

class GameApp(ttk.Frame):
    # ...

    def animate(self):
        if not self.is_stopped:
            self.pre_update()

            remaining_elements = []
            for element in self.elements:
                element.update()
                element.render()

                if element.to_be_deleted:
                    element.delete()
                else:
                    remaining_elements.append(element)

            self.elements = remaining_elements

            self.post_update()

        self.after(self.update_delay, self.animate)

We also add a few helper methods for collision detection to Sprite. (Implementations are in utils.py)

class GameCanvasElement(GameElement):
    # ...

    def distance_to(self, element):
        return distance(self.x, self.y, element.x, element.y)

    def is_within_distance(self, element, d):
        return self.distance_to(element) <= d

SpaceGame

SpaceGame is the main class. It maintains a Ship, a list of Enemies, and a list of Bullets.

  • It keeps bullets and enemies in self.bullets and self.enemies. The reason these objects are kept outside the typical self.elements is to improve performance when performing collision detection.
  • There are 2 mechanisms to generate enemies.
    def create_enemy_star(self):
        # ...

    def create_enemy_from_edges(self):
        # ...

    def create_enemies(self):
        if random() < 0.2:
            enemies = self.create_enemy_star()
        else:
            enemies = self.create_enemy_from_edges()

        for e in enemies:
            self.add_enemy(e)
  • It runs collision detection to detect bullet-enemy collisions and enemy-ship collisions.
  • It handles keyboard events (both key-pressed and key-released events).
  • It also deals with bomb capacity of the ship: detonates the bomb, maintains bomb cool-down periods, and shows/hides bomb radius after it is detonated.

Ship

Ship (code in elements.py) maintains ship movement. It cruises forward with constant speed. The user can only change the ship's direction by turning left and right. It also generate bullets with method fire:

    def fire(self):
        if self.app.bullet_count() >= MAX_NUM_BULLETS:
            return

        dx,dy = direction_to_dxdy(self.direction)

        bullet = Bullet(self.app, self.x, self.y, dx * BULLET_BASE_SPEED, dy * BULLET_BASE_SPEED)

        self.app.add_bullet(bullet)

This code leaves rooms for more creativity in creating bullets.


Bullet and Enemy

Bomb

Getting started

This is an individual assignment, but you should still use branches in git for managing your work. You should use the following template as a starter code.

Since this is the second time you work on design patterns, the instructions would be less specific and you can use your judgement more freely to improve the code.

Patterns

Additional improvements