====== Tetris Take 2 ====== 作成日: 2023-07-21 (金) [[https://youtu.be/83rdvO2K_P8|初心者によるC++入門 #34 ブロックの基礎になるクラスを作る]] {{:youtube:tetris_take2.png?400|}} ==== main.cpp ==== #include #include #include "board.h" #include "gfxaux.h" 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, 10} }; if (SDL_Init(SDL_INIT_VIDEO) < 0) { std::cerr << "Error: init SDL\n"; std::exit(1); } SDL_Window *window = SDL_CreateWindow( "HelloSDL window", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, ScreenWidth, ScreenHeight, 0); if (window == nullptr) { std::cerr << "Error: create window\n"; std::exit(1); } SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED); if (renderer == nullptr) { std::cerr << "Error: create renderer\n"; std::exit(1); } // setup game Fence fence = setup_fence(board, Gray, White); // game loop bool running = true; while (running) { SDL_Event event; while (SDL_PollEvent(&event)) { if (event.type == SDL_QUIT) { running = false; } } SDL_SetRenderDrawColor(renderer, 100, 100, 255, 255); SDL_RenderClear(renderer); draw_fence(renderer, fence); SDL_RenderPresent(renderer); SDL_Delay(1); } SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window); return 0; } ==== gfxaux.h ==== #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); #endif ==== gfxaux.cpp ==== #include "gfxaux.h" void draw_rectangle(SDL_Renderer *renderer, SDL_Rect const &rect, SDL_Color const &fc, SDL_Color const &oc) { SDL_SetRenderDrawColor(renderer, fc.r, fc.g, fc.b, fc.a); SDL_RenderFillRect(renderer, &rect); SDL_SetRenderDrawColor(renderer, oc.r, oc.g, oc.b, oc.a); SDL_RenderDrawRect(renderer, &rect); } ==== board.h ==== #ifndef BOARD_H #define BOARD_H #include "cell.h" #include #include struct BoardInfo { int arena_width; int arena_height; int cell_width; int cell_height; SDL_Point position; }; using Fence = std::vector; Fence setup_fence(BoardInfo const &board, SDL_Color const &fill_color, SDL_Color const &outline_color); void draw_fence(SDL_Renderer *renderer, Fence const &fence); #endif ==== board.cpp ==== #include "board.h" #include "gfxaux.h" #include "cell.h" Fence setup_fence(BoardInfo const &board, SDL_Color const &fill_color, SDL_Color const &outline_color) { Fence fence; // left wall for (int i{}; i < board.arena_height; ++i) { SDL_Point pt{0, i * board.cell_height}; fence.emplace_back(&board, board.position, pt, fill_color, outline_color); } // right wall for (int i{}; i < board.arena_height; ++i) { SDL_Point pt{(board.arena_width + 1) * board.cell_width, i * board.cell_height}; fence.emplace_back(&board, board.position, pt, fill_color, outline_color); } // floor for (int i{}; i < board.arena_width + 2; ++i) { SDL_Point pt{i * board.cell_width, board.arena_height * board.cell_height}; fence.emplace_back(&board, board.position, pt, fill_color, outline_color); } return fence; } void draw_fence(SDL_Renderer *renderer, Fence const &fence) { for (Cell const &cell : fence) { cell.draw(renderer); } } ==== cell.h ==== #ifndef CELL_H #define CELL_H #include struct BoardInfo; class Cell { public: Cell(BoardInfo const *board, SDL_Point const &origin, SDL_Point const &position, SDL_Color const &fill_color, SDL_Color const &outline_color); ~Cell() = default; SDL_Point global_position() const; SDL_Point local_position() const; void draw(SDL_Renderer *renderer) const; private: BoardInfo const *board_; SDL_Point origin_; SDL_Point position_; SDL_Color fill_color_; SDL_Color outline_color_; }; #endif ==== cell.cpp ==== #include "cell.h" #include "gfxaux.h" #include "board.h" Cell::Cell(BoardInfo const *board, SDL_Point const &origin, SDL_Point const &position, SDL_Color const &fill_color, SDL_Color const &outline_color) : board_{board} , origin_{origin} , position_{position} , fill_color_{fill_color} , outline_color_{outline_color} { } SDL_Point Cell::global_position() const { return {origin_.x + position_.x, origin_.y + position_.y}; } SDL_Point Cell::local_position() const { return position_; } void Cell::draw(SDL_Renderer *renderer) const { auto [x, y] = global_position(); SDL_Rect rect{x, y, board_->cell_width, board_->cell_height}; draw_rectangle(renderer, rect, fill_color_, outline_color_); } ==== Makefile ==== SRCS = \ main.cpp \ board.cpp \ gfxaux.cpp \ cell.cpp OBJS = ${SRCS:%.cpp=%.o} DEPS = ${SRCS:%.cpp=%.d} EXECUTABLE = tetris.exe CXXFLAGS = -IC:\SDL2\include LDFLAGS = -LC:\SDL2\lib LDLIBS = -lmingw32 -lSDL2main -lSDL2 .PHONY: all all: ${EXECUTABLE} ${EXECUTABLE}: ${OBJS} ${CXX} -o $@ $^ ${LDFLAGS} ${LDLIBS} %.o: %.cpp ${CXX} -c -o $@ $< -MMD -MP ${CXXFLAGS} .PHONY: clean clean: ${RM} ${EXECUTABLE} ${OBJS} ${DEPS} -include ${DEPS} ''C:\SDL2''の部分は、SDLをインストールした場所を指定します。