【Tank】6.0 坦克动起来、渲染次数优化、坦克碰撞检测

Here's a structured breakdown of the code and its components, focusing on the architecture and key concepts: --- ### **1. Abstract Classes and Interfaces** - **`AbstractModel`** - **Properties**: `width`, `height`, `name`, `canvas` (abstract) - **Methods**: `render()`, `getImage()` - **Purpose**: Defines the interface for all models. The `canvas` property is resolved in derived classes (e.g., `Tank`, `Straw`). - **Key**: Abstract properties allow decoupling of logic (e.g., `canvas` is resolved in `Tank`). - **`IModel`** - **Properties**: `x`, `y`, `width`, `height`, `canvas` - **Methods**: `render()`, `getImage()` - **Purpose**: Enforces contract for all models. `canvas` is a property, not a method, to avoid duplication. - **Key**: Encapsulates shared behavior (e.g., `x`, `y`, `width`, `height`). - **`ICanvas`** - **Properties**: `ctx` (abstract), `models` (array of `IModel`) - **Methods**: `render()`, `model()`, `num()` - **Purpose**: Abstracts the canvas logic. `model()` returns a constructor function (e.g., `Tank`), and `num()` specifies how many models to create. - **Key**: Decouples canvas logic from models, enabling reuse (e.g., `Tank` uses `straw` for its canvas). --- ### **2. Model Implementation** - **`Tank` (extends `AbstractModel`)** - **Canvas**: `canvas = straw` (resolved in `Tank`'s constructor). - **Render Logic**: - `render()`: Calls `super.draw()` (base class) and adds random direction adjustment. - `move()`: - Moves the tank based on current direction. - Checks for collisions with other models (e.g., `water`, `wallBrick`). - Adjusts direction if collision detected. - **Collision Detection**: - Bounding box checks (`leftX`, `rightX`, `topY`, `bottomY`). - Uses `models.some()` to check against all other models. - **`Straw` (extends `AbstractModel`)** - **Canvas**: `canvas = straw` (resolved in `Straw`'s constructor). - **Render Logic**: - `render()`: Calls `super.draw()` (base class). - `getImage()`: Returns image for `straw` (e.g., `strawTop`). - **`WallBrick` / `WallSteel` / `Water`** - Similar to `Straw`, but with different images and collision logic (e.g., `water` has different collision checks). --- ### **3. Canvas Handling** - **`Tank` (extends `AbstractCanvas`)** - **Methods**: - `render()`: - Calls `createModels()` to generate instances of `Tank`, `Straw`, etc. - Calls `renderModels()` to draw all models. - `createModels()`: - Uses `position.position()` to generate coordinates. - Adds models to `models` array for rendering. - `renderModels()`: - Clears the canvas and draws all models. - **Key Optimization**: - **Abstract `canvas` property**: `Tank` uses `straw` for its canvas, which is resolved in `Tank`'s constructor. - **Reusability**: `Straw`, `WallBrick`, `Water` share the same `render()` and `getImage()` logic but differ in images and collision checks. --- ### **4. Collision Detection** - **Logic**: - **Bounding Box Checks**: - For each model, checks if the tank's position overlaps with another model's bounding box. - Returns `true` if no overlap (i.e., collision detected). - **Random Direction Adjustment**: - In `Tank`'s `render()`, `random(20) == 1` randomly sets direction to `EnumDirection.bottom` (for enemy tanks). --- ### **5. Key Design Choices** - **Abstraction**: - `AbstractModel` and `ICanvas` abstract implementation details (e.g., `canvas` is resolved in derived classes). - `model()` returns a constructor function (e.g., `Tank`) to avoid duplication. - **Reusability**: - `Straw`, `WallBrick`, `Water` share the same `render()` and `getImage()` logic but differ in images and collision checks. - **Performance**: - `move()` uses a `while` loop to minimize redundant redraws. - `renderModels()` clears the canvas before drawing, reducing overhead. --- ### **6. Summary** - **Architecture**: - Models (e.g., `Tank`) extend `AbstractModel`, which implements `IModel`. - `Canvas` (e.g., `Tank`) extends `AbstractCanvas`, which implements `ICanvas`. - **Key Features**: - **Collision Detection**: Bounding box checks for all models. - **Randomization**: Enemy tanks have a chance to move downward. - **Optimization**: Abstract properties, reusability, and minimal redundant code. - **Benefits**: - Modular design with separation of concerns. - Easy to add new models (e.g., `Airplane`) by extending `AbstractModel`. This structure ensures flexibility, maintainability, and performance in a game engine context.