今度から、1レポジトリでやります
このコミットが含まれているのは:
コミット
5a9f93e4ea
|
@ -0,0 +1 @@
|
||||||
|
pong
|
|
@ -0,0 +1,2 @@
|
||||||
|
# 1.0.0
|
||||||
|
* 最初リリース
|
|
@ -0,0 +1,24 @@
|
||||||
|
NAME=pong
|
||||||
|
VERSION=1.0.0
|
||||||
|
# Linux、Haiku、かIllumos = /usr、FreeBSDかOpenBSD = /usr/local、NetBSD = /usr/pkg
|
||||||
|
PREFIX=/usr/local
|
||||||
|
CC=clang++
|
||||||
|
CFLAGS=-I${PREFIX}/include -L${PREFIX}/lib
|
||||||
|
LDFLAGS=-lSDL2 -lSDL2_ttf
|
||||||
|
FILES=main.cc
|
||||||
|
|
||||||
|
all:
|
||||||
|
${CC} ${CFLAGS} -o ${NAME} ${FILES} ${LDFLAGS}
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f ${NAME}
|
||||||
|
|
||||||
|
install: all
|
||||||
|
mkdir -p ${DESTDIR}${PREFIX}/bin
|
||||||
|
cp -f ${NAME} ${DESTDIR}${PREFIX}/bin
|
||||||
|
chmod 755 ${DESTDIR}${PREFIX}/bin/${NAME}
|
||||||
|
|
||||||
|
uninstall:
|
||||||
|
rm -f ${DESTDIR}${PREFIX}/bin/${NAME}
|
||||||
|
|
||||||
|
.PHONY: all clean install uninstall
|
バイナリファイルは表示されません。
|
@ -0,0 +1,37 @@
|
||||||
|
# pong
|
||||||
|
|
||||||
|
初めてSDLだけでゲームを作りました。\
|
||||||
|
2時間以内で完成しました。
|
||||||
|
|
||||||
|
このpongゲームはレベルアップシステムがあり、レベルが上がると徐々に難しくなります。\
|
||||||
|
また、NPCが10ポイントを獲得すると、ゲームオーバーになります。
|
||||||
|
|
||||||
|
## 勉強点
|
||||||
|
* C++、超ひさしぶりですから(´・ω・`)
|
||||||
|
* SDL2(今まではC言語だけで座ったことがある)
|
||||||
|
* フォントライブラリ
|
||||||
|
* スコア
|
||||||
|
* プレイヤーの移動
|
||||||
|
* NPCの移動
|
||||||
|
* レベルアップ
|
||||||
|
* ゲームオーバー
|
||||||
|
* ゲームループ
|
||||||
|
|
||||||
|
## ソフト
|
||||||
|
* SDL2
|
||||||
|
* SDL2_ttf
|
||||||
|
|
||||||
|
## Linux
|
||||||
|
```sh
|
||||||
|
make
|
||||||
|
```
|
||||||
|
|
||||||
|
## \*BSD
|
||||||
|
```sh
|
||||||
|
gmake
|
||||||
|
```
|
||||||
|
|
||||||
|
## Illumos
|
||||||
|
```sh
|
||||||
|
gmake PREFIX=/usr
|
||||||
|
```
|
|
@ -0,0 +1,256 @@
|
||||||
|
#include <SDL2/SDL.h>
|
||||||
|
#include <SDL2/SDL_ttf.h>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#define WIDTH 720
|
||||||
|
#define HEIGHT 720
|
||||||
|
#define FONTSIZE 32
|
||||||
|
#define BALLSIZE 16
|
||||||
|
#define BALLSPEED 16
|
||||||
|
#define SPEED 9
|
||||||
|
#define PI 3.1415926535897323846
|
||||||
|
|
||||||
|
SDL_Renderer* renderer;
|
||||||
|
SDL_Window* window;
|
||||||
|
TTF_Font* font;
|
||||||
|
SDL_Color color;
|
||||||
|
bool running;
|
||||||
|
int frameCount, timerFPS, lastFrame, fps;
|
||||||
|
|
||||||
|
SDL_Rect player, npc, ball, scoreboard, leveldisplay;
|
||||||
|
float xvelocity, yvelocity, ballvelocity, ballsize;
|
||||||
|
std::string score, slevel;
|
||||||
|
int lscore, rscore, level, games;
|
||||||
|
bool turn, isgameover;
|
||||||
|
std::string version = "1.0.0";
|
||||||
|
|
||||||
|
void serve() {
|
||||||
|
player.y = npc.y = (HEIGHT/2) - (player.h/2);
|
||||||
|
if (turn) {
|
||||||
|
ball.x = player.x + (player.w * 4);
|
||||||
|
xvelocity = (BALLSPEED*ballvelocity)/2;
|
||||||
|
turn = false;
|
||||||
|
} else {
|
||||||
|
ball.x = npc.x - (player.w * 4);
|
||||||
|
xvelocity = -(BALLSPEED*ballvelocity)/2;
|
||||||
|
turn = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
yvelocity = 0;
|
||||||
|
ball.y = HEIGHT / 2 - ((BALLSIZE-ballsize)/2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void write(std::string text, int x, int y) {
|
||||||
|
SDL_Surface *surface;
|
||||||
|
SDL_Texture *texture;
|
||||||
|
const char* t = text.c_str();
|
||||||
|
|
||||||
|
surface = TTF_RenderText_Solid(font, t, color);
|
||||||
|
texture = SDL_CreateTextureFromSurface(renderer, surface);
|
||||||
|
|
||||||
|
// スコアボード
|
||||||
|
scoreboard.w = surface->w;
|
||||||
|
scoreboard.h = surface->h;
|
||||||
|
scoreboard.x = x - scoreboard.w;
|
||||||
|
scoreboard.y = y - scoreboard.h;
|
||||||
|
|
||||||
|
// レベル表示
|
||||||
|
leveldisplay.w = surface->w;
|
||||||
|
leveldisplay.h = surface->h;
|
||||||
|
leveldisplay.x = x - scoreboard.w + 8;
|
||||||
|
leveldisplay.y = y - scoreboard.h + 8;
|
||||||
|
|
||||||
|
// 掃除
|
||||||
|
SDL_FreeSurface(surface);
|
||||||
|
SDL_RenderCopy(renderer, texture, NULL, &scoreboard);
|
||||||
|
SDL_DestroyTexture(texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gameover() {
|
||||||
|
xvelocity = yvelocity = ballvelocity = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void update() {
|
||||||
|
// ボールとコンピュータの衝突検出
|
||||||
|
if (SDL_HasIntersection(&ball, &npc)) {
|
||||||
|
double rel = (npc.y + (npc.h / 2)) - (ball.y + ((BALLSIZE-ballsize) / 2));
|
||||||
|
double norm = rel / (npc.h / 2);
|
||||||
|
double bounce = norm * (5 * PI / 12);
|
||||||
|
xvelocity = -(BALLSPEED*ballvelocity) * cos(bounce);
|
||||||
|
yvelocity = (BALLSPEED*ballvelocity) * -sin(bounce);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ボールとプレイヤーの衝突検出
|
||||||
|
if (SDL_HasIntersection(&ball, &player)) {
|
||||||
|
double rel = (player.y + (player.h / 2)) - (ball.y + ((BALLSIZE-ballsize) / 2));
|
||||||
|
double norm = rel / (player.h / 2);
|
||||||
|
double bounce = norm * (5 * PI / 12);
|
||||||
|
xvelocity = (BALLSPEED*ballvelocity) * cos(bounce);
|
||||||
|
yvelocity = (BALLSPEED*ballvelocity) * -sin(bounce);
|
||||||
|
}
|
||||||
|
|
||||||
|
// コンピュータがボールの方向を付いてくる
|
||||||
|
if (ball.y > npc.y + (npc.h/2)) npc.y += ((SPEED+level*0.5f)*ballvelocity);
|
||||||
|
if (ball.y < npc.y + (npc.h/2)) npc.y -= ((SPEED+level*0.5f)*ballvelocity);
|
||||||
|
|
||||||
|
// ボールが左右に逃げたら、スコアアップにして、最初フレームから再開
|
||||||
|
if (ball.x <= 0) {
|
||||||
|
rscore++;
|
||||||
|
serve();
|
||||||
|
} else if (ball.x + (BALLSIZE-ballsize) >= WIDTH) {
|
||||||
|
lscore++;
|
||||||
|
serve();
|
||||||
|
games++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// コンピュータさんを十分倒したら、レベルアップにする
|
||||||
|
if (games == ((level + 1) * 2)) {
|
||||||
|
level++;
|
||||||
|
ballvelocity += 0.25f;
|
||||||
|
ballsize -= 0.2f;
|
||||||
|
games = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// コンピュータのスコアが10になったら、ゲームオーバーだ
|
||||||
|
if (rscore > 9) {
|
||||||
|
isgameover = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ボールが上下に逃げる事に対して守る
|
||||||
|
if (ball.y <= 0 || ball.y + (BALLSIZE-ballsize) >= HEIGHT) yvelocity = -yvelocity;
|
||||||
|
|
||||||
|
// ボールの移動
|
||||||
|
ball.x += xvelocity;
|
||||||
|
ball.y += yvelocity;
|
||||||
|
|
||||||
|
// スコアやレベルの文字
|
||||||
|
score = std::to_string(lscore) + " " + std::to_string(rscore);
|
||||||
|
slevel = "Lv" + std::to_string(level);
|
||||||
|
|
||||||
|
// プレイヤーを上下に逃げられない為
|
||||||
|
if (player.y < 0) player.y = 0;
|
||||||
|
if (player.y + player.h > HEIGHT) player.y = HEIGHT-player.h;
|
||||||
|
|
||||||
|
// コンピューターを上下に逃げられない為
|
||||||
|
if (npc.y < 0) npc.y = 0;
|
||||||
|
if (npc.y + npc.h > HEIGHT) npc.y = HEIGHT-npc.h;
|
||||||
|
}
|
||||||
|
|
||||||
|
void input() {
|
||||||
|
SDL_Event e;
|
||||||
|
const Uint8 *keystates = SDL_GetKeyboardState(NULL);
|
||||||
|
|
||||||
|
while (SDL_PollEvent(&e)) {
|
||||||
|
if (e.type == SDL_QUIT) {
|
||||||
|
running = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keystates[SDL_SCANCODE_Q]) running = false; // Qでゲームを終了
|
||||||
|
if (!isgameover) {
|
||||||
|
if (keystates[SDL_SCANCODE_UP]) player.y -= (SPEED*ballvelocity); // ↑でプレイヤーを上がる
|
||||||
|
if (keystates[SDL_SCANCODE_DOWN]) player.y += (SPEED*ballvelocity); // ↓でプレイヤーを下げる
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void render() {
|
||||||
|
// 黒色背景
|
||||||
|
SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0x00, 255);
|
||||||
|
SDL_RenderClear(renderer);
|
||||||
|
|
||||||
|
frameCount++;
|
||||||
|
timerFPS = SDL_GetTicks() - lastFrame;
|
||||||
|
if (timerFPS < (1000/60)) {
|
||||||
|
SDL_Delay((1000/60) - timerFPS);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 背景以外もレンダーして
|
||||||
|
SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, 255);
|
||||||
|
|
||||||
|
// プレイヤー、コンピュータ、とボールを創作
|
||||||
|
if (!isgameover) {
|
||||||
|
SDL_RenderFillRect(renderer, &player);
|
||||||
|
SDL_RenderFillRect(renderer, &npc);
|
||||||
|
SDL_RenderFillRect(renderer, &ball);
|
||||||
|
}
|
||||||
|
|
||||||
|
write(score, WIDTH/2+FONTSIZE, FONTSIZE*2);
|
||||||
|
write(slevel, WIDTH/2+FONTSIZE, FONTSIZE*3);
|
||||||
|
if (isgameover) {
|
||||||
|
write("GAME OVER", WIDTH/2+84, HEIGHT/2);
|
||||||
|
}
|
||||||
|
write("076.moe SUWAKO NO PONG v" + version, WIDTH-150, HEIGHT-20);
|
||||||
|
SDL_RenderPresent(renderer);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
// SDLを初期化
|
||||||
|
if (SDL_Init(SDL_INIT_EVERYTHING) < 0) {
|
||||||
|
std::cout << "SDL_Init()に失敗" << '\n';
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ウィンドウとレンダーを創作
|
||||||
|
if (SDL_CreateWindowAndRenderer(WIDTH, HEIGHT, 0, &window, &renderer) < 0) {
|
||||||
|
std::cout << "SDL_CreateWindowAndRenderer()に失敗" << '\n';
|
||||||
|
SDL_Quit();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// フォントを読込
|
||||||
|
TTF_Init();
|
||||||
|
font = TTF_OpenFont("Peepo.ttf", FONTSIZE);
|
||||||
|
if (!font) {
|
||||||
|
std::cout << "フォントを読込に失敗" << '\n';
|
||||||
|
SDL_DestroyRenderer(renderer);
|
||||||
|
SDL_DestroyWindow(window);
|
||||||
|
SDL_Quit();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初期設定
|
||||||
|
running = true;
|
||||||
|
static int lastTime = 0;
|
||||||
|
|
||||||
|
color.r = color.g = color.b = 255;
|
||||||
|
lscore = rscore = games = 0;
|
||||||
|
ballvelocity = ballsize = 1.0f;
|
||||||
|
level = 1;
|
||||||
|
player.x = 32;
|
||||||
|
player.h = (HEIGHT/4)/(ballsize*1.15f);
|
||||||
|
player.y = (HEIGHT/2) - (player.h/2);
|
||||||
|
player.w = 12;
|
||||||
|
npc = player;
|
||||||
|
npc.x = WIDTH - npc.w - 32;
|
||||||
|
ball.w = ball.h = (BALLSIZE-ballsize);
|
||||||
|
|
||||||
|
serve();
|
||||||
|
|
||||||
|
// ゲームループ
|
||||||
|
while (running) {
|
||||||
|
lastFrame = SDL_GetTicks();
|
||||||
|
if (lastFrame >= (lastTime + 1000)) {
|
||||||
|
lastTime = lastFrame;
|
||||||
|
fps = frameCount;
|
||||||
|
frameCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isgameover) {
|
||||||
|
update();
|
||||||
|
input();
|
||||||
|
render();
|
||||||
|
} else {
|
||||||
|
gameover();
|
||||||
|
input();
|
||||||
|
render();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 掃除
|
||||||
|
TTF_CloseFont(font);
|
||||||
|
SDL_DestroyRenderer(renderer);
|
||||||
|
SDL_DestroyWindow(window);
|
||||||
|
SDL_Quit();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
brickbreaker
|
|
@ -0,0 +1,15 @@
|
||||||
|
NAME=brickbreaker
|
||||||
|
# Linux、Haiku、かIllumos = /usr、FreeBSDかOpenBSD = /usr/local、NetBSD = /usr/pkg
|
||||||
|
PREFIX=/usr/local
|
||||||
|
CC=clang++
|
||||||
|
CFLAGS=-I${PREFIX}/include -L${PREFIX}/lib
|
||||||
|
LDFLAGS=-lSDL2 -lSDL2_mixer -lSDL2_ttf
|
||||||
|
FILES=main.cc src/ball.cc src/brick.cc src/render.cc
|
||||||
|
|
||||||
|
all:
|
||||||
|
${CC} ${CFLAGS} -o ${NAME} ${FILES} ${LDFLAGS}
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f ${NAME}
|
||||||
|
|
||||||
|
.PHONY: all clean
|
|
@ -0,0 +1,32 @@
|
||||||
|
# ブリックブレイカー
|
||||||
|
|
||||||
|
7つレベルがあり、レベルを上がるとより難しくなります。\
|
||||||
|
「YOU WIN」と表示されたら、ハイスコアを教えて下さいね。(´・ω・`)
|
||||||
|
|
||||||
|
## 音楽
|
||||||
|
[Stas Gavrikさんより](https://youtube.owacon.moe/playlist?list=PLyc7oozhSJMytXF1eWMUAU2zl84W0Nkqg)
|
||||||
|
|
||||||
|
## 勉強点
|
||||||
|
* BGM
|
||||||
|
* オブジェクト指向プログラミング
|
||||||
|
* オブジェクトを非表示にする事
|
||||||
|
|
||||||
|
## ソフト
|
||||||
|
* SDL2
|
||||||
|
* SDL2_mixer
|
||||||
|
* SDL2_ttf
|
||||||
|
|
||||||
|
## Linux
|
||||||
|
```sh
|
||||||
|
make
|
||||||
|
```
|
||||||
|
|
||||||
|
## \*BSD
|
||||||
|
```sh
|
||||||
|
gmake
|
||||||
|
```
|
||||||
|
|
||||||
|
## Illumos
|
||||||
|
```sh
|
||||||
|
gmake PREFIX=/usr
|
||||||
|
```
|
バイナリファイルは表示されません。
バイナリファイルは表示されません。
バイナリファイルは表示されません。
バイナリファイルは表示されません。
バイナリファイルは表示されません。
バイナリファイルは表示されません。
バイナリファイルは表示されません。
バイナリファイルは表示されません。
|
@ -0,0 +1,76 @@
|
||||||
|
#include <SDL2/SDL.h>
|
||||||
|
#include <SDL2/SDL_ttf.h>
|
||||||
|
#include <SDL2/SDL_mixer.h>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "src/render.hh"
|
||||||
|
#include "src/ball.hh"
|
||||||
|
#include "src/player.hh"
|
||||||
|
#include "src/brick.hh"
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
Render r;
|
||||||
|
Player p(r);
|
||||||
|
Ball bl(r, p);
|
||||||
|
Brick br(r);
|
||||||
|
|
||||||
|
if (SDL_Init(SDL_INIT_EVERYTHING) < 0) {
|
||||||
|
std::cout << "SDL_Init()に失敗" << '\n';
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SDL_CreateWindowAndRenderer(r.width, r.height, 0, &r.window, &r.renderer) < 0) {
|
||||||
|
std::cout << "SDL_CreateWindowAndRenderer()に失敗" << '\n';
|
||||||
|
SDL_Quit();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 2048) < 0) {
|
||||||
|
std::cout << "Mix_OpenAudio()に失敗" << '\n';
|
||||||
|
SDL_DestroyRenderer(r.renderer);
|
||||||
|
SDL_DestroyWindow(r.window);
|
||||||
|
SDL_Quit();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_SetWindowTitle(r.window, "ブリックブレイカー");
|
||||||
|
|
||||||
|
TTF_Init();
|
||||||
|
r.font = TTF_OpenFont("font.ttf", r.fontsize);
|
||||||
|
if (!r.font) {
|
||||||
|
std::cout << "フォントを読込に失敗" << '\n';
|
||||||
|
SDL_DestroyRenderer(r.renderer);
|
||||||
|
SDL_DestroyWindow(r.window);
|
||||||
|
Mix_CloseAudio();
|
||||||
|
SDL_Quit();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int lastTime = 0;
|
||||||
|
br.resetBricks(r, p, bl);
|
||||||
|
|
||||||
|
while (r.running) {
|
||||||
|
r.lastFrame = SDL_GetTicks();
|
||||||
|
if (r.lastFrame >= lastTime + 1000) {
|
||||||
|
lastTime = r.lastFrame;
|
||||||
|
r.fps = r.frameCount;
|
||||||
|
r.frameCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!r.gameover) {
|
||||||
|
r.update(r, p, bl, br);
|
||||||
|
}
|
||||||
|
r.input(p);
|
||||||
|
r.render(p, bl, br);
|
||||||
|
}
|
||||||
|
|
||||||
|
TTF_CloseFont(r.font);
|
||||||
|
SDL_DestroyRenderer(r.renderer);
|
||||||
|
SDL_DestroyWindow(r.window);
|
||||||
|
SDL_Quit();
|
||||||
|
Mix_FreeMusic(r.music);
|
||||||
|
Mix_CloseAudio();
|
||||||
|
TTF_Quit();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
#include "ball.hh"
|
||||||
|
|
||||||
|
void Ball::resetBall(Render &r, Player &p) {
|
||||||
|
p.player.x = (r.width / 2) - (p.player.w / 2);
|
||||||
|
Ball::ball.y = p.player.y - (p.player.h * 4);
|
||||||
|
Ball::yvelocity = Ball::ballspeed / 2;
|
||||||
|
Ball::xvelocity = 0;
|
||||||
|
Ball::ball.x = r.width / 2 - (Ball::size / 2);
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
#ifndef BALL_H
|
||||||
|
#define BALL_H
|
||||||
|
|
||||||
|
#include <SDL2/SDL.h>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "player.hh"
|
||||||
|
|
||||||
|
class Ball {
|
||||||
|
public:
|
||||||
|
float ballspeed = 8.0f;
|
||||||
|
int size = 16;
|
||||||
|
|
||||||
|
float xvelocity;
|
||||||
|
float yvelocity;
|
||||||
|
|
||||||
|
SDL_Rect ball;
|
||||||
|
|
||||||
|
void resetBall(Render &r, Player &p);
|
||||||
|
|
||||||
|
Ball(Render& r, Player& p) {
|
||||||
|
ball.y = p.player.y - (p.player.h / 2);
|
||||||
|
yvelocity = ballspeed / 2;
|
||||||
|
xvelocity = ball.x = 0;
|
||||||
|
ball.w = ball.h = size;
|
||||||
|
ball.x = r.width / 2 - (size / 2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,67 @@
|
||||||
|
#include <SDL2/SDL.h>
|
||||||
|
#include <SDL2/SDL_mixer.h>
|
||||||
|
#include <SDL2/SDL_ttf.h>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "render.hh"
|
||||||
|
#include "player.hh"
|
||||||
|
#include "ball.hh"
|
||||||
|
#include "brick.hh"
|
||||||
|
|
||||||
|
void Brick::resetBricks(Render &r, Player &p, Ball &bl) {
|
||||||
|
srand(static_cast<unsigned int>(time(nullptr)));
|
||||||
|
r.c1r = rand() % 256;
|
||||||
|
r.c1g = rand() % 256;
|
||||||
|
r.c1b = rand() % 256;
|
||||||
|
r.c2r = rand() % 256;
|
||||||
|
r.c2g = rand() % 256;
|
||||||
|
r.c2b = rand() % 256;
|
||||||
|
r.c3r = rand() % 256;
|
||||||
|
r.c3g = rand() % 256;
|
||||||
|
r.c3b = rand() % 256;
|
||||||
|
r.c4r = rand() % 256;
|
||||||
|
r.c4g = rand() % 256;
|
||||||
|
r.c4b = rand() % 256;
|
||||||
|
r.c5r = rand() % 256;
|
||||||
|
r.c5g = rand() % 256;
|
||||||
|
r.c5b = rand() % 256;
|
||||||
|
r.c6r = rand() % 256;
|
||||||
|
r.c6g = rand() % 256;
|
||||||
|
r.c6b = rand() % 256;
|
||||||
|
|
||||||
|
|
||||||
|
if (r.level > 1) {
|
||||||
|
Mix_HaltMusic();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string music = "ass/" + std::to_string(r.level) + ".ogg";
|
||||||
|
r.music = Mix_LoadMUS(music.c_str());
|
||||||
|
if (Mix_PlayMusic(r.music, -1) < 0) {
|
||||||
|
std::cout << "OGGファイルのエラー:" << Mix_GetError() << '\n';
|
||||||
|
r.running = false;
|
||||||
|
TTF_CloseFont(r.font);
|
||||||
|
SDL_DestroyRenderer(r.renderer);
|
||||||
|
SDL_DestroyWindow(r.window);
|
||||||
|
SDL_Quit();
|
||||||
|
Mix_CloseAudio();
|
||||||
|
TTF_Quit();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < Brick::col * Brick::row; i++) {
|
||||||
|
Brick::bricks[i] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bl.size -= 2;
|
||||||
|
bl.ballspeed += 1.4f;
|
||||||
|
p.player.w -= 1.4f;
|
||||||
|
p.player.x = (r.width / 2) - (p.player.w / 2);
|
||||||
|
bl.ball.y = p.player.y - (p.player.h * 4);
|
||||||
|
bl.yvelocity = bl.ballspeed / 2;
|
||||||
|
bl.xvelocity = 0;
|
||||||
|
bl.ball.x = r.width / 2 - (bl.size / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Brick::setBricks(int i) {
|
||||||
|
Brick::brick.x = (((i%Brick::col) + 1) * Brick::gaps) + ((i%Brick::col) * Brick::brick.w) - (Brick::gaps/2);
|
||||||
|
Brick::brick.y = Brick::brick.h * 3 + (((i%Brick::row) + 1) * Brick::gaps) + ((i%Brick::row) * Brick::brick.h) - (Brick::gaps/2);
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
#ifndef BRICK_H
|
||||||
|
#define BRICK_H
|
||||||
|
|
||||||
|
#include <SDL2/SDL.h>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "render.hh"
|
||||||
|
#include "player.hh"
|
||||||
|
#include "ball.hh"
|
||||||
|
|
||||||
|
class Brick {
|
||||||
|
public:
|
||||||
|
int col = 7;
|
||||||
|
int row = 5;
|
||||||
|
int gaps = 16;
|
||||||
|
|
||||||
|
bool bricks[7*5];
|
||||||
|
|
||||||
|
SDL_Color color = {255, 255, 255};
|
||||||
|
SDL_Rect brick;
|
||||||
|
|
||||||
|
void resetBricks(Render &r, Player &p, Ball &bl);
|
||||||
|
void setBricks(int i);
|
||||||
|
|
||||||
|
Brick(Render& r) {
|
||||||
|
brick.w = (r.width - (gaps * col)) / col;
|
||||||
|
brick.h = 22;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,25 @@
|
||||||
|
#ifndef PLAYER_H
|
||||||
|
#define PLAYER_H
|
||||||
|
|
||||||
|
#include <SDL2/SDL.h>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "render.hh"
|
||||||
|
|
||||||
|
class Player {
|
||||||
|
public:
|
||||||
|
SDL_Rect player, lives;
|
||||||
|
|
||||||
|
int score = 0;
|
||||||
|
int scoreMultiplier = 1;
|
||||||
|
int livesCount = 3;
|
||||||
|
|
||||||
|
Player(Render& r) {
|
||||||
|
player.h = 12;
|
||||||
|
player.y = r.height - player.h - 32;
|
||||||
|
player.w = r.width / 4;
|
||||||
|
player.x = (r.width / 2) - (player.w / 2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,170 @@
|
||||||
|
#include "render.hh"
|
||||||
|
#include "ball.hh"
|
||||||
|
#include "player.hh"
|
||||||
|
#include "brick.hh"
|
||||||
|
|
||||||
|
#define PI 3.14
|
||||||
|
|
||||||
|
void Render::gameOver(Player &p, Brick &br, bool winner) {
|
||||||
|
if (winner) {
|
||||||
|
Render::winner = true;
|
||||||
|
} else {
|
||||||
|
Render::winner = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Render::gameover = true;
|
||||||
|
Mix_HaltMusic();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Render::write(Player &p, Brick &br, std::string text, int x, int y) {
|
||||||
|
SDL_Surface *surface;
|
||||||
|
SDL_Texture *texture;
|
||||||
|
const char* t = text.c_str();
|
||||||
|
surface = TTF_RenderText_Solid(Render::font, t, br.color);
|
||||||
|
texture = SDL_CreateTextureFromSurface(Render::renderer, surface);
|
||||||
|
|
||||||
|
p.lives.w = surface->w;
|
||||||
|
p.lives.h = surface->h;
|
||||||
|
p.lives.x = x - p.lives.w;
|
||||||
|
p.lives.y = y - p.lives.h;
|
||||||
|
|
||||||
|
SDL_FreeSurface(surface);
|
||||||
|
SDL_RenderCopy(Render::renderer, texture, NULL, &p.lives);
|
||||||
|
SDL_DestroyTexture(texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Render::update(Render &r, Player &p, Ball &bl, Brick &br) {
|
||||||
|
if (p.livesCount <= 0) {
|
||||||
|
gameOver(p, br, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SDL_HasIntersection(&bl.ball, &p.player)) {
|
||||||
|
double rel = (p.player.x + ((float)p.player.w/2)) - ((float)bl.ball.x + ((float)bl.size/2));
|
||||||
|
double norm = rel / ((float)p.player.w/2);
|
||||||
|
double bounce = norm * (5*PI/12);
|
||||||
|
|
||||||
|
bl.yvelocity = -bl.ballspeed * cos(bounce);
|
||||||
|
bl.xvelocity = bl.ballspeed * -sin(bounce);
|
||||||
|
p.scoreMultiplier = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bl.ball.y <= 0) {
|
||||||
|
bl.yvelocity = -bl.yvelocity;
|
||||||
|
}
|
||||||
|
if (bl.ball.y + bl.size >= Render::height) {
|
||||||
|
bl.yvelocity = -bl.yvelocity;
|
||||||
|
p.livesCount--;
|
||||||
|
bl.resetBall(r, p);
|
||||||
|
}
|
||||||
|
if (bl.ball.x <= 0 || bl.ball.x + bl.size >= Render::width) {
|
||||||
|
bl.xvelocity = -bl.xvelocity;
|
||||||
|
}
|
||||||
|
bl.ball.x += bl.xvelocity;
|
||||||
|
bl.ball.y += bl.yvelocity;
|
||||||
|
if (p.player.x < 0) {
|
||||||
|
p.player.x = 0;
|
||||||
|
}
|
||||||
|
if (p.player.x + p.player.w > Render::width) {
|
||||||
|
p.player.x = Render::width - p.player.w;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool reset = true;
|
||||||
|
for (int i = 0; i < br.col*br.row; i++) {
|
||||||
|
br.setBricks(i);
|
||||||
|
|
||||||
|
if (SDL_HasIntersection(&bl.ball, &br.brick) && br.bricks[i]) {
|
||||||
|
br.bricks[i] = 0;
|
||||||
|
p.score += 100 * p.scoreMultiplier;
|
||||||
|
p.scoreMultiplier++;
|
||||||
|
|
||||||
|
if (bl.ball.x >= br.brick.x) {
|
||||||
|
bl.xvelocity = -bl.xvelocity;
|
||||||
|
bl.ball.x -= 1;
|
||||||
|
}
|
||||||
|
if (bl.ball.x <= br.brick.x) {
|
||||||
|
bl.xvelocity = -bl.xvelocity;
|
||||||
|
bl.ball.x += 1;
|
||||||
|
}
|
||||||
|
if (bl.ball.y <= br.brick.y) {
|
||||||
|
bl.yvelocity = -bl.yvelocity;
|
||||||
|
bl.xvelocity = -bl.xvelocity;
|
||||||
|
bl.ball.y -= 1;
|
||||||
|
}
|
||||||
|
if (bl.ball.y >= br.brick.y) {
|
||||||
|
bl.yvelocity = -bl.yvelocity;
|
||||||
|
bl.xvelocity = -bl.xvelocity;
|
||||||
|
bl.ball.y += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (br.bricks[i]) {
|
||||||
|
reset = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reset) {
|
||||||
|
Render::level++;
|
||||||
|
if (r.level > 7) {
|
||||||
|
gameOver(p, br, true);
|
||||||
|
} else {
|
||||||
|
br.resetBricks(r, p, bl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Render::input(Player &p) {
|
||||||
|
SDL_Event e;
|
||||||
|
const Uint8 *keystates = SDL_GetKeyboardState(NULL);
|
||||||
|
|
||||||
|
while (SDL_PollEvent(&e)) {
|
||||||
|
if (e.type == SDL_QUIT) {
|
||||||
|
Render::running = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keystates[SDL_SCANCODE_Q]) Render::running = false;
|
||||||
|
if (!Render::gameover) {
|
||||||
|
if (keystates[SDL_SCANCODE_LEFT]) p.player.x -= Render::xpos;
|
||||||
|
if (keystates[SDL_SCANCODE_RIGHT]) p.player.x += Render::xpos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Render::render(Player &p, Ball &bl, Brick &br) {
|
||||||
|
SDL_SetRenderDrawColor(Render::renderer, 0x00, 0x00, 0x00, 255);
|
||||||
|
SDL_RenderClear(Render::renderer);
|
||||||
|
|
||||||
|
Render::frameCount++;
|
||||||
|
Render::timerFPS = SDL_GetTicks() - Render::lastFrame;
|
||||||
|
|
||||||
|
if (Render::timerFPS < (1000/60)) {
|
||||||
|
SDL_Delay((1000/60) - Render::timerFPS);
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_SetRenderDrawColor(Render::renderer, 255, 255, 255, 255);
|
||||||
|
SDL_RenderFillRect(Render::renderer, &p.player);
|
||||||
|
SDL_RenderFillRect(Render::renderer, &bl.ball);
|
||||||
|
write(p, br, "SCORE: " + std::to_string(p.score), Render::width, Render::fontsize*1.5f);
|
||||||
|
write(p, br, "LIVES: " + std::to_string(p.livesCount), 130, Render::fontsize*1.5f);
|
||||||
|
write(p, br, "LEVEL: " + std::to_string(Render::level), 130, Render::fontsize*3.5f);
|
||||||
|
|
||||||
|
if (Render::gameover) {
|
||||||
|
if (Render::winner) write(p, br, "YOU WIN", Render::width/2+Render::fontsize, Render::height/2);
|
||||||
|
else write(p, br, "YOU LOSS", Render::width/2+Render::fontsize, Render::height/2);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < br.col*br.row; i++) {
|
||||||
|
SDL_SetRenderDrawColor(Render::renderer, c1r, c1g, c1b, 255);
|
||||||
|
if (i%2 == 0) SDL_SetRenderDrawColor(Render::renderer, c2r, c2g, c2b, 255);
|
||||||
|
if (i%3 == 0) SDL_SetRenderDrawColor(Render::renderer, c3r, c3g, c3b, 255);
|
||||||
|
if (i%4 == 0) SDL_SetRenderDrawColor(Render::renderer, c4r, c4g, c4b, 255);
|
||||||
|
if (i%5 == 0) SDL_SetRenderDrawColor(Render::renderer, c5r, c5g, c5b, 255);
|
||||||
|
if (i%6 == 0) SDL_SetRenderDrawColor(Render::renderer, c6r, c6g, c6b, 255);
|
||||||
|
|
||||||
|
if (br.bricks[i]) {
|
||||||
|
br.setBricks(i);
|
||||||
|
SDL_RenderFillRect(Render::renderer, &br.brick);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_RenderPresent(Render::renderer);
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
#ifndef RENDER_H
|
||||||
|
#define RENDER_H
|
||||||
|
|
||||||
|
#include <SDL2/SDL.h>
|
||||||
|
#include <SDL2/SDL_ttf.h>
|
||||||
|
#include <SDL2/SDL_mixer.h>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
class Player;
|
||||||
|
class Ball;
|
||||||
|
class Brick;
|
||||||
|
|
||||||
|
class Render {
|
||||||
|
public:
|
||||||
|
bool running, gameover, winner;
|
||||||
|
int frameCount, timerFPS, lastFrame, fps = 0;
|
||||||
|
|
||||||
|
int width = 620;
|
||||||
|
int height = 720;
|
||||||
|
int fontsize = 16;
|
||||||
|
int xpos = 9;
|
||||||
|
int level = 1;
|
||||||
|
|
||||||
|
// 色
|
||||||
|
int c1r, c1g, c1b;
|
||||||
|
int c2r, c2g, c2b;
|
||||||
|
int c3r, c3g, c3b;
|
||||||
|
int c4r, c4g, c4b;
|
||||||
|
int c5r, c5g, c5b;
|
||||||
|
int c6r, c6g, c6b;
|
||||||
|
|
||||||
|
SDL_Window *window;
|
||||||
|
SDL_Renderer *renderer;
|
||||||
|
TTF_Font* font;
|
||||||
|
Mix_Music* music;
|
||||||
|
|
||||||
|
void update(Render &r, Player &p, Ball &bl, Brick &br);
|
||||||
|
void input(Player &p);
|
||||||
|
void render(Player &p, Ball &bl, Brick &br);
|
||||||
|
|
||||||
|
Render() {
|
||||||
|
winner = false;
|
||||||
|
gameover = false;
|
||||||
|
running = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void gameOver(Player &p, Brick &br, bool winner);
|
||||||
|
void write(Player &p, Brick &br, std::string text, int x, int y);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
読み込み中…
新しいイシューから参照