youtube:cpp-intro-035
差分
このページの2つのバージョン間の差分を表示します。
両方とも前のリビジョン前のリビジョン次のリビジョン | 前のリビジョン | ||
youtube:cpp-intro-035 [2024/02/28 18:26] – 削除 - 外部編集 (不明な日付) 127.0.0.1 | youtube:cpp-intro-035 [2024/02/29 11:53] (現在) – [Tetris Take 3] freemikan | ||
---|---|---|---|
行 1: | 行 1: | ||
+ | ====== Tetris Take 3 ====== | ||
+ | |||
+ | 作成日: 2023-07-21 (金) | ||
+ | |||
+ | [[https:// | ||
+ | |||
+ | {{: | ||
+ | |||
+ | ==== main.cpp ==== | ||
+ | |||
+ | <file cpp> | ||
+ | #include < | ||
+ | #include < | ||
+ | |||
+ | #include " | ||
+ | #include " | ||
+ | #include " | ||
+ | |||
+ | int main(int argc, char **argv) { | ||
+ | int const ScreenWidth = 600; // px | ||
+ | int const ScreenHeight = 550; // px | ||
+ | | ||
+ | BoardInfo board { | ||
+ | 10, 20, | ||
+ | 24, 24, | ||
+ | SDL_Point{10, | ||
+ | }; | ||
+ | |||
+ | if (SDL_Init(SDL_INIT_VIDEO) < 0) { | ||
+ | std::cerr << " | ||
+ | std:: | ||
+ | } | ||
+ | | ||
+ | SDL_Window *window = SDL_CreateWindow( | ||
+ | " | ||
+ | SDL_WINDOWPOS_CENTERED, | ||
+ | SDL_WINDOWPOS_CENTERED, | ||
+ | ScreenWidth, | ||
+ | ScreenHeight, | ||
+ | 0); | ||
+ | if (window == nullptr) { | ||
+ | std::cerr << " | ||
+ | std:: | ||
+ | } | ||
+ | | ||
+ | SDL_Renderer *renderer = SDL_CreateRenderer(window, | ||
+ | if (renderer == nullptr) { | ||
+ | std::cerr << " | ||
+ | std:: | ||
+ | } | ||
+ | | ||
+ | // setup game | ||
+ | Fence fence = setup_fence(board, | ||
+ | CoordMediator coord_mediator{& | ||
+ | Shape test_shape{& | ||
+ | Shape test_shape2{& | ||
+ | |||
+ | // game loop | ||
+ | bool running = true; | ||
+ | while (running) { | ||
+ | SDL_Event event; | ||
+ | while (SDL_PollEvent(& | ||
+ | if (event.type == SDL_QUIT) { | ||
+ | running = false; | ||
+ | } | ||
+ | } | ||
+ | | ||
+ | SDL_SetRenderDrawColor(renderer, | ||
+ | SDL_RenderClear(renderer); | ||
+ | |||
+ | draw_fence(renderer, | ||
+ | test_shape.draw(renderer); | ||
+ | test_shape2.draw(renderer); | ||
+ | | ||
+ | SDL_RenderPresent(renderer); | ||
+ | | ||
+ | SDL_Delay(1); | ||
+ | } | ||
+ | | ||
+ | SDL_DestroyRenderer(renderer); | ||
+ | SDL_DestroyWindow(window); | ||
+ | SDL_Quit(); | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==== gfxaux.h ==== | ||
+ | |||
+ | <file cpp> | ||
+ | #ifndef GFXAUX_H | ||
+ | #define GFXAUX_H | ||
+ | |||
+ | #include < | ||
+ | |||
+ | SDL_Color const Gray{128, 128, 128, 255}; | ||
+ | SDL_Color const White{255, 255, 255, 255}; | ||
+ | |||
+ | void draw_rectangle(SDL_Renderer *renderer, SDL_Rect const &rect, SDL_Color const &fc, SDL_Color const &oc); | ||
+ | |||
+ | struct RenderStates { | ||
+ | int tx = 0; | ||
+ | int ty = 0; | ||
+ | }; | ||
+ | |||
+ | #endif | ||
+ | </ | ||
+ | |||
+ | ==== gfxaux.cpp ==== | ||
+ | |||
+ | <file cpp> | ||
+ | #include " | ||
+ | |||
+ | void draw_rectangle(SDL_Renderer *renderer, SDL_Rect const &rect, SDL_Color const &fc, SDL_Color const &oc) { | ||
+ | SDL_SetRenderDrawColor(renderer, | ||
+ | SDL_RenderFillRect(renderer, | ||
+ | SDL_SetRenderDrawColor(renderer, | ||
+ | SDL_RenderDrawRect(renderer, | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==== board.h ==== | ||
+ | |||
+ | <file cpp> | ||
+ | #ifndef BOARD_H | ||
+ | #define BOARD_H | ||
+ | |||
+ | #include " | ||
+ | #include < | ||
+ | #include < | ||
+ | |||
+ | struct BoardInfo { | ||
+ | int arena_width; | ||
+ | int arena_height; | ||
+ | int cell_width; | ||
+ | int cell_height; | ||
+ | SDL_Point position; | ||
+ | }; | ||
+ | |||
+ | class CoordMediator { | ||
+ | public: | ||
+ | CoordMediator(BoardInfo const *board); | ||
+ | SDL_Point arena_to_pixel(SDL_Point const &arena) const; | ||
+ | SDL_Point pixel_to_arena(SDL_Point const &pixel) const; | ||
+ | SDL_Point arena_origin() const; | ||
+ | BoardInfo const *board_info() const; | ||
+ | |||
+ | private: | ||
+ | BoardInfo const *board_; | ||
+ | }; | ||
+ | |||
+ | using Fence = std:: | ||
+ | |||
+ | Fence setup_fence(BoardInfo const &board, | ||
+ | SDL_Color const & | ||
+ | SDL_Color const & | ||
+ | |||
+ | void draw_fence(SDL_Renderer *renderer, Fence const & | ||
+ | |||
+ | #endif | ||
+ | </ | ||
+ | |||
+ | ==== board.cpp ==== | ||
+ | |||
+ | <file cpp> | ||
+ | #include " | ||
+ | |||
+ | #include " | ||
+ | #include " | ||
+ | |||
+ | CoordMediator:: | ||
+ | : board_{board} | ||
+ | {} | ||
+ | |||
+ | SDL_Point CoordMediator:: | ||
+ | int x = arena.x * board_-> | ||
+ | int y = arena.y * board_-> | ||
+ | return {x, y}; | ||
+ | } | ||
+ | |||
+ | SDL_Point CoordMediator:: | ||
+ | int x = pixel.x / board_-> | ||
+ | int y = pixel.y / board_-> | ||
+ | return {x, y}; | ||
+ | } | ||
+ | |||
+ | SDL_Point CoordMediator:: | ||
+ | int x = board_-> | ||
+ | int y = board_-> | ||
+ | return {x, y}; | ||
+ | } | ||
+ | |||
+ | BoardInfo const *CoordMediator:: | ||
+ | return board_; | ||
+ | } | ||
+ | |||
+ | Fence setup_fence(BoardInfo const &board, | ||
+ | SDL_Color const & | ||
+ | SDL_Color const & | ||
+ | Fence fence; | ||
+ | | ||
+ | // left wall | ||
+ | for (int i{}; i < board.arena_height; | ||
+ | SDL_Point pt{0, i * board.cell_height}; | ||
+ | fence.emplace_back(& | ||
+ | } | ||
+ | |||
+ | // right wall | ||
+ | for (int i{}; i < board.arena_height; | ||
+ | SDL_Point pt{(board.arena_width + 1) * board.cell_width, | ||
+ | fence.emplace_back(& | ||
+ | } | ||
+ | |||
+ | // floor | ||
+ | for (int i{}; i < board.arena_width + 2; ++i) { | ||
+ | SDL_Point pt{i * board.cell_width, | ||
+ | fence.emplace_back(& | ||
+ | } | ||
+ | |||
+ | return fence; | ||
+ | } | ||
+ | |||
+ | void draw_fence(SDL_Renderer *renderer, Fence const &fence) { | ||
+ | RenderStates states{}; | ||
+ | for (Cell const &cell : fence) { | ||
+ | cell.draw(renderer, | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==== cell.h ==== | ||
+ | |||
+ | <file cpp> | ||
+ | #ifndef CELL_H | ||
+ | #define CELL_H | ||
+ | |||
+ | #include < | ||
+ | |||
+ | struct BoardInfo; | ||
+ | struct RenderStates; | ||
+ | |||
+ | class Cell { | ||
+ | public: | ||
+ | Cell(BoardInfo const *board, | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | ~Cell() = default; | ||
+ | | ||
+ | SDL_Point global_position() const; | ||
+ | SDL_Point local_position() const; | ||
+ | | ||
+ | void draw(SDL_Renderer *renderer, RenderStates states) const; | ||
+ | |||
+ | private: | ||
+ | BoardInfo const *board_; | ||
+ | SDL_Point origin_; | ||
+ | SDL_Point position_; | ||
+ | SDL_Color fill_color_; | ||
+ | SDL_Color outline_color_; | ||
+ | }; | ||
+ | |||
+ | #endif | ||
+ | </ | ||
+ | |||
+ | ==== cell.cpp ==== | ||
+ | |||
+ | <file cpp> | ||
+ | #include " | ||
+ | |||
+ | #include " | ||
+ | #include " | ||
+ | |||
+ | Cell:: | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | : board_{board} | ||
+ | , origin_{origin} | ||
+ | , position_{position} | ||
+ | , fill_color_{fill_color} | ||
+ | , outline_color_{outline_color} { | ||
+ | } | ||
+ | |||
+ | SDL_Point Cell:: | ||
+ | return {origin_.x + position_.x, | ||
+ | } | ||
+ | |||
+ | SDL_Point Cell:: | ||
+ | return position_; | ||
+ | } | ||
+ | |||
+ | void Cell:: | ||
+ | auto [x, y] = global_position(); | ||
+ | SDL_Rect rect{x + states.tx, y + states.ty, | ||
+ | board_-> | ||
+ | draw_rectangle(renderer, | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==== block.h ==== | ||
+ | |||
+ | <file cpp> | ||
+ | #ifndef BLOCK_H | ||
+ | #define BLOCK_H | ||
+ | |||
+ | #include " | ||
+ | #include < | ||
+ | |||
+ | struct RenderStates; | ||
+ | class CoordMediator; | ||
+ | class Shape; | ||
+ | |||
+ | class Block { | ||
+ | public: | ||
+ | Block(CoordMediator const *coord_mediator, | ||
+ | SDL_Point const & | ||
+ | SDL_Color const &fc, | ||
+ | SDL_Color const &oc, | ||
+ | Shape const *parent = nullptr); | ||
+ | | ||
+ | SDL_Point local_position() const; | ||
+ | SDL_Point global_position() const; | ||
+ | void draw(SDL_Renderer *renderer, RenderStates states) const; | ||
+ | |||
+ | private: | ||
+ | Cell cell_; | ||
+ | CoordMediator const *coord_mediator_; | ||
+ | SDL_Point position_; | ||
+ | Shape const *parent_; | ||
+ | }; | ||
+ | |||
+ | #endif | ||
+ | </ | ||
+ | |||
+ | ==== block.cpp ==== | ||
+ | |||
+ | <file cpp> | ||
+ | #include " | ||
+ | |||
+ | #include " | ||
+ | #include " | ||
+ | #include " | ||
+ | |||
+ | namespace { | ||
+ | Cell create_cell(CoordMediator const *mediator, | ||
+ | | ||
+ | | ||
+ | auto *board = mediator-> | ||
+ | auto origin = mediator-> | ||
+ | return Cell{board, origin, SDL_Point{0, | ||
+ | } | ||
+ | } // ns anon | ||
+ | |||
+ | Block:: | ||
+ | | ||
+ | | ||
+ | | ||
+ | Shape const *parent) | ||
+ | : cell_{create_cell(coord_mediator, | ||
+ | , coord_mediator_{coord_mediator} | ||
+ | , position_{position} | ||
+ | , parent_{parent} | ||
+ | {} | ||
+ | | ||
+ | SDL_Point Block:: | ||
+ | return position_; | ||
+ | } | ||
+ | |||
+ | SDL_Point Block:: | ||
+ | if (parent_ == nullptr) { | ||
+ | return position_; | ||
+ | } | ||
+ | auto [px, py] = parent_-> | ||
+ | return {px + position_.x, | ||
+ | } | ||
+ | |||
+ | void Block:: | ||
+ | states.tx += position_.x; | ||
+ | states.ty += position_.y; | ||
+ | auto [tx, ty] = coord_mediator_-> | ||
+ | cell_.draw(renderer, | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==== shape.h ==== | ||
+ | |||
+ | <file cpp> | ||
+ | #ifndef SHAPE_H | ||
+ | #define SHAPE_H | ||
+ | |||
+ | #include " | ||
+ | #include < | ||
+ | #include < | ||
+ | |||
+ | class CoordMediator; | ||
+ | |||
+ | class Shape { | ||
+ | public: | ||
+ | Shape(CoordMediator const *coord_mediator, | ||
+ | SDL_Point const & | ||
+ | SDL_Color const &fc, | ||
+ | SDL_Color const &oc); | ||
+ | | ||
+ | SDL_Point local_position() const; | ||
+ | SDL_Point global_position() const; | ||
+ | void draw(SDL_Renderer *renderer) const; | ||
+ | |||
+ | private: | ||
+ | std:: | ||
+ | CoordMediator const *coord_mediator_; | ||
+ | SDL_Point position_; | ||
+ | }; | ||
+ | |||
+ | #endif | ||
+ | </ | ||
+ | |||
+ | ==== shape.cpp ==== | ||
+ | |||
+ | <file cpp> | ||
+ | #include " | ||
+ | |||
+ | #include " | ||
+ | #include " | ||
+ | #include " | ||
+ | |||
+ | Shape:: | ||
+ | | ||
+ | | ||
+ | | ||
+ | : coord_mediator_{coord_mediator} | ||
+ | , position_{position} | ||
+ | { | ||
+ | blocks_.emplace_back(coord_mediator_, | ||
+ | blocks_.emplace_back(coord_mediator_, | ||
+ | blocks_.emplace_back(coord_mediator_, | ||
+ | blocks_.emplace_back(coord_mediator_, | ||
+ | } | ||
+ | |||
+ | SDL_Point Shape:: | ||
+ | return position_; | ||
+ | } | ||
+ | |||
+ | SDL_Point Shape:: | ||
+ | return position_; | ||
+ | } | ||
+ | |||
+ | void Shape:: | ||
+ | RenderStates states{position_.x, | ||
+ | for (auto &block : blocks_) { | ||
+ | block.draw(renderer, | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==== Makefile ==== | ||
+ | |||
+ | <file makefile> | ||
+ | SRCS = \ | ||
+ | main.cpp \ | ||
+ | board.cpp \ | ||
+ | gfxaux.cpp \ | ||
+ | cell.cpp \ | ||
+ | block.cpp \ | ||
+ | shape.cpp | ||
+ | | ||
+ | OBJS = ${SRCS: | ||
+ | DEPS = ${SRCS: | ||
+ | EXECUTABLE = tetris.exe | ||
+ | CXXFLAGS = -IC: | ||
+ | LDFLAGS = -LC: | ||
+ | LDLIBS = -lmingw32 -lSDL2main -lSDL2 | ||
+ | |||
+ | .PHONY: all | ||
+ | all: ${EXECUTABLE} | ||
+ | |||
+ | ${EXECUTABLE}: | ||
+ | ${CXX} -o $@ $^ ${LDFLAGS} ${LDLIBS} | ||
+ | |||
+ | %.o: %.cpp | ||
+ | ${CXX} -c -o $@ $< -MMD -MP ${CXXFLAGS} | ||
+ | |||
+ | .PHONY: clean | ||
+ | clean: | ||
+ | ${RM} ${EXECUTABLE} ${OBJS} ${DEPS} | ||
+ | |||
+ | -include ${DEPS} | ||
+ | </ | ||