コミット
This commit is contained in:
2
CHANGELOG.md
Normal file
2
CHANGELOG.md
Normal file
@@ -0,0 +1,2 @@
|
||||
# 1.0.0
|
||||
* 最初リリース
|
||||
24
Makefile
Normal file
24
Makefile
Normal file
@@ -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
|
||||
37
README.md
Normal file
37
README.md
Normal file
@@ -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
|
||||
```
|
||||
256
main.cc
Normal file
256
main.cc
Normal file
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user