iTranslated by AI
[Week 2] Day 3: Block Placement and Destruction (Fixed Stage)
Day 3: Block Placement + Destruction (Fixed 1-Stage)
Day 3 advances the project to a state where "blocks break and the game starts to feel like a game."
-
Add the
Blockclass -
Give
GameScenea block array and place them in a fixed single stage

-
Implement collision detection between the ball's AABB and the block's AABB
-
Destroy (remove) the collided block

-
Add scoring (a placeholder score is fine for Day 3)
-
Clear the stage when all blocks are destroyed (provisionally move to
ResultScenefor Day 3)
Durability (HP) will be added on Day 5, and the multi-stage system on Day 6.
Today's Goal (Done)
- Add
Block(AABB + rendering) - Place blocks (rows x columns)
- Destroy blocks upon ball collision
- Provisional clear transition when all blocks are destroyed
List of Modified Files
Added (Full content)
src/Game/Block.hsrc/Game/Block.cpp
Modified (Full content as of today)
src/Game/Ball.hsrc/Game/Ball.cppsrc/Scene/GameScene.hsrc/Scene/GameScene.cpp
Implementation Strategy (Day 3)
Collision Handling (Keep it simple for Day 3)
Since we will improve reflection quality on Day 4, the priority for Day 3 is just to "make them break."
- Reflect on the Y-axis (provisional) upon collision
- Refine overlap correction on Day 4
Block Management
- Use
std::vector<Block> - Manage survival status using
Block::alive - Render and perform collision detection only for alive blocks
Added Files (Full Content)
src/Game/Block.h
#pragma once
#include "Aabb.h"
enum class QualityLevel;
class Block
{
public:
Block() = default;
Block(float l, float t, float r, float b);
void Draw(QualityLevel q, int ox, int oy) const;
Aabb GetAabb() const { return m_aabb; }
bool IsAlive() const { return m_alive; }
void Kill() { m_alive = false; }
private:
Aabb m_aabb{};
bool m_alive = true;
};
src/Game/Block.cpp
#include "Block.h"
#include "../Core/Quality.h"
#include "DxLib.h"
Block::Block(float l, float t, float r, float b)
{
m_aabb.l = l;
m_aabb.t = t;
m_aabb.r = r;
m_aabb.b = b;
m_alive = true;
}
void Block::Draw(QualityLevel q, int ox, int oy) const
{
if (!m_alive) return;
const int x0 = (int)m_aabb.l + ox;
const int y0 = (int)m_aabb.t + oy;
const int x1 = (int)m_aabb.r + ox;
const int y1 = (int)m_aabb.b + oy;
// Change the look slightly based on Quality (without being heavy)
const int fill = (q == QualityLevel::High)
? GetColor(80, 170, 240)
: GetColor(60, 120, 170);
DrawBox(x0, y0, x1, y1, fill, TRUE);
DrawBox(x0, y0, x1, y1, GetColor(20, 20, 30), FALSE);
}
Modification: GameScene.h (Diff: Adding Block array and functions)
#pragma once
#include "IScene.h"
#include <vector>
class SceneManager;
class Camera2D;
class Paddle;
class Ball;
class Block;
class GameScene : public IScene
{
public:
explicit GameScene(SceneManager* mgr);
~GameScene();
void Enter() override;
void Update(float dt, const class Input& input) override;
void Draw() override;
private:
SceneManager* m_mgr = nullptr;
Camera2D* m_camera = nullptr;
Paddle* m_paddle = nullptr;
Ball* m_ball = nullptr;
std::vector<Block> m_blocks;
int m_lives = 3;
int m_score = 0;
float m_time = 0.0f;
void BuildStage_();
void CheckBallVsBlocks_();
int AliveBlocks_() const;
};
Modification: GameScene.cpp (Diff: Stage generation + Collision processing)
Enter(): BuildStage_()
void GameScene::Enter()
{
m_time = 0.0f;
m_lives = 3;
m_score = 0;
m_camera->Reset();
m_paddle->Reset();
m_ball->ResetOnPaddle(*m_paddle);
BuildStage_();
}
BuildStage_(): emplace_back Block with rows/cols
void GameScene::BuildStage_()
{
m_blocks.clear();
// Fixed 1-stage (Stage system to be added on Day 6)
const int rows = 5;
const int cols = 10;
const float pad = 6.0f;
const float bw = 100.0f;
const float bh = 28.0f;
const float startX = 80.0f;
const float startY = 120.0f;
for (int r = 0; r < rows; r++)
{
for (int c = 0; c < cols; c++)
{
const float x0 = startX + c * (bw + pad);
const float y0 = startY + r * (bh + pad);
const float x1 = x0 + bw;
const float y1 = y0 + bh;
m_blocks.emplace_back(x0, y0, x1, y1);
}
}
}
CheckBallVsBlocks_():
void GameScene::CheckBallVsBlocks_()
{
const Aabb ball = m_ball->GetAabb();
for (auto& blk : m_blocks)
{
if (!blk.IsAlive()) continue;
const Aabb a = blk.GetAabb();
if (!IntersectAabb(a, ball)) continue;
blk.Kill();
m_score += 100; // Placeholder for Day 3
Audio::Instance().PlaySe("hit");
// Provisional for Day 3: Only Y-axis reflection
m_ball->BounceY();
break; // Destroy only one block per frame
}
}
AliveBlocks_():
Count surviving blocks
int GameScene::AliveBlocks_() const
{
int n = 0;
for (const auto& b : m_blocks)
if (b.IsAlive()) n++;
return n;
}
Operation Check Checklist
- Blocks are displayed
- Blocks disappear when hit by the ball
- Only one block is destroyed per frame (controlled by break)
- Score is increased
-
Transition to
ResultScenewhen all blocks are cleared (provisional clear)
Things to do on Day 4 (Preview)
Day 4 is the day to improve reflection quality.
- Correctly reflect X/Y based on "which side was hit"
- Overlap correction (push-back)
- Replace reflection on block collision from
BounceY()
Day 3 focuses on reaching the "destruction" functionality as quickly as possible, and Day 4 will focus on refining the quality.
Discussion