main.h
#include "Game.h"
int main()
{
Game tetris;
while (tetris.window.isOpen())
{
tetris.gameRun();
}
return 0;
}
Game.h
#pragma once
#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>
#include <windows.h>
#include <iostream>
#include <sstream>
#include "Tetris.h"
using namespace sf;
class Game
{
public:
Game();
~Game();
sf::RenderWindow window;
Tetris player1, player2;
bool gameOver, gameQuit;
Clock clock;
int Window_width, Window_height, stageWidth, stageHeight;
bool isGameBegin; //--------->游戏是否开始
int isGameOverState; //--------->游戏结束的状态
Vector2i mCornPoint; //游戏区域位置
int gridSize; //块的大小
int imgBGno, imgSkinNo;
Texture tTiles;
Texture tBackground, tButtons, tSwitcher, tFrame, tCover, tScore, tGameOver; //创建纹理对象
Sprite sTiles;
Sprite sBackground, sButtons, sSwitcher, sFrame, sCover, sScore, sGameOver; //创建精灵对象
IntRect ButtonRectStart, ButtonRectHold, ButtonRectLeft, ButtonRectRight;
int ButtonState_Start, ButtonState_Hold;
SoundBuffer sbWin;
Sound soundWin;
Music bgMusic;
Clock gameClock;
void gameInitial();
void LoadMediaData();
void gameInput();
void gameLogic();
void gameDraw();
void gameRun();
};
Game.cpp
#include "Game.h"
Game::Game()
{
Window_width = 1350;
Window_height = 1000;
imgBGno = 1;
imgSkinNo = 1;
window.create(sf::VideoMode(Window_width, Window_height), L"Tetris");
}
Game::~Game()
{
}
void Game::gameInitial()
{
window.setFramerateLimit(15); //设置游戏帧频
LoadMediaData();
player1.role = rolePLAYER1; //定义Tetris对象为player1
player2.role = rolePLAYER2; //定义Tetris对象为player2
player1.Initial(&tTiles); //将方块的素材传给Tetris对象, 由Tetris对象绘制方块
player2.Initial(&tTiles);
}
void Game::LoadMediaData()
{
std::stringstream ss;
ss << "data/images/bg" << imgBGno << ".jpg";
if (!tBackground.loadFromFile(ss.str()))//加载纹理图片
std::cout << "BK image 没有找到" << std::endl;
ss.str("");//清空字符串
ss << "data/images/tiles" << imgSkinNo << ".jpg";
if (!tTiles.loadFromFile(ss.str()))//加载纹理图片
std::cout << "tiles image 没有找到" << std::endl;
if (!tFrame.loadFromFile("data/images/frame.png"))//加载纹理照片
std::cout << "tFrame image 没有找到" << std::endl;
if (!tCover.loadFromFile("data/images/cover.png"))//加载纹理照片
std::cout << "tCover image 没有找到" << std::endl;
if (!tGameOver.loadFromFile("data/images/end.png"))//加载纹理照片
std::cout << "tGameOver image 没有找到" << std::endl;
sBackground.setTexture(tBackground);//设置精灵对象的纹理
//sTiles.setTexture(tTiles); //由Tetris对象绘制方块,两个玩家各自绘自己的方块
sFrame.setTexture(tFrame);
sCover.setTexture(tCover);
sGameOver.setTexture(tGameOver);
}
void Game::gameInput()
{
sf::Event event;
window.setKeyRepeatEnabled(false);//按键按下只相应一次
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
{
window.close();
gameQuit = true;
}
player1.Iuput(event);
player2.Iuput(event);
}
}
void Game::gameLogic()
{
float time = clock.getElapsedTime().asSeconds();
clock.restart();
player1.timer += time;
player2.timer += time;
player1.Logic();
player2.Logic();
}
void Game::gameDraw()
{
window.clear();// 清屏
//绘制背景
sBackground.setPosition(0, 0);
window.draw(sBackground);
window.draw(sFrame);
player1.Draw(&window);
player2.Draw(&window);
window.display();
}
void Game::gameRun()
{
do
{
gameInitial();
while (window.isOpen() && gameOver == false)
{
gameInput();
gameLogic();
gameDraw();
}
} while (!gameQuit);
}
Tetris.h
#pragma once
#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>
#include <windows.h>
#include <iostream>
#include <sstream>
#define GRIDSIZE 35
#define STAGE_WIDTH 10
#define STAGE_HEIGHT 20
#define P1_STAGE_CORNER_X 156
#define P1_STAGE_CORNER_Y 174
#define P2_STAGE_CORNER_X 844
#define P2_STAGE_CORNER_Y 174
typedef enum PLAYROLE {
roleNONE, //空
rolePLAYER1, //玩家1
rolePLAYER2, //玩家2
};
using namespace sf;
class Tetris
{
public:
Tetris();
~Tetris();
Vector2i mCornPoint; //游戏区域位置
int role;
int gridSize; //块的大小
int imgBGno, imgSkinNo;
Texture *tTiles;
Texture tBackground, tButtons, tNum, tTimer, tCounter, tGameOver; //创建纹理对象
Sprite sBackground, sTiles, sButtons, sNum, sTimer, sCounter, sGameOver; //创建精灵对象
int Field[STAGE_HEIGHT][STAGE_HEIGHT] = { 0 };
Vector2i currentSquare[4], nextSquare[4], holdSquare[4], tempSquare[4];
int Figures[7][4] =
{
3,5,1,7, //I
4,5,2,7, //S
4,5,3,6, //Z
5,3,4,7, //T
3,5,2,7, //L
7,5,3,6, //J
2,3,4,5, //O
};
int dx;
bool rotate;
int colorNum;
float timer, delay;
void Initial(Texture *tex);
void Iuput(sf::Event event);
void Logic();
void Draw(sf::RenderWindow* window);
bool hitTest();
};
Tetris.cpp
#include "Tetris.h"
Tetris::Tetris()
{
dx = 0; // X方向偏移量
rotate = false; //是否旋转
colorNum = 1; //色块的颜色
timer = 0; //计时间隔
delay = 0.3; //方块下落的速度
}
Tetris::~Tetris()
{
}
void Tetris::Initial(Texture *tex)
{
tTiles = tex;
if (role == rolePLAYER1)
{
mCornPoint = { P1_STAGE_CORNER_X,P1_STAGE_CORNER_Y };
}
if (role == rolePLAYER2)
{
mCornPoint = { P2_STAGE_CORNER_X,P2_STAGE_CORNER_Y };
}
sTiles.setTexture(*tTiles);
//初始化方块图形
colorNum = 1 + rand() % 7;
int n = rand() % 7;
for (int i = 0; i < 4; i++)
{
currentSquare[i].x = Figures[n][i] % 2;
currentSquare[i].y = Figures[n][i] / 2;
}
}
void Tetris::Iuput(sf::Event event)
{
if (role == rolePLAYER1)//玩家1的按键响应
{
if (event.type == Event::KeyPressed)
{
if (event.key.code == Keyboard::W)
rotate = true;
if (event.key.code == Keyboard::A)
dx = -1;
else if (event.key.code == Keyboard::D)
dx = 1;
if (event.key.code == Keyboard::S)
delay = 0.05;
}
if (event.type == Event::KeyReleased)
{
if (event.key.code == Keyboard::A || event.key.code == Keyboard::D)
dx = 0;
if (event.key.code == Keyboard::S)
delay = 0.3;
}
}
if (role == rolePLAYER2)
{
if (event.type == Event::KeyPressed)
{
if (event.key.code == Keyboard::Up)
rotate = true;
if (event.key.code == Keyboard::Left)
dx = -1;
else if (event.key.code == Keyboard::Right)
dx = 1;
if (event.key.code == Keyboard::Down)
delay = 0.05;
}
if (event.type == Event::KeyReleased)
{
if (event.key.code == Keyboard::Left || event.key.code == Keyboard::Right)
dx = 0;
if (event.key.code == Keyboard::Down)
delay = 0.3; //时间响应间隔变大,方块下降速度变慢
}
}
}
void Tetris::Logic()
{
///<- 水平 Move ->///
for (int i = 0; i < 4; i++)
{
tempSquare[i] = currentSquare[i];
currentSquare[i].x += dx;
}
if (!hitTest())//如果撞上了
for (int i = 0; i < 4; i++)
currentSquare[i] = tempSquare[i];//方块左右如果有障碍,则不能向障碍方向移动
///<- 旋转 rotate ->///
if (rotate)
{
Vector2i p = currentSquare[1]; //设置旋转中心点
for (int i = 0; i < 4; i++)
{//顺时针旋转90度
int x = currentSquare[i].y - p.y;//原Y方向距离中心点的差值,作为新的差值, 传递给X方向
int y = currentSquare[i].x - p.x;//原X方向距离中心点的差值,作为新的差值, 传递给Y方向
currentSquare[i].x = p.x - x;//新坐标X=中心点坐标-新的X方向差值
currentSquare[i].y = p.y - y;//新坐标Y=中心点坐标-新的Y方向差值
}
if (!hitTest())//如果撞上了
for (int i = 0; i < 4; i++)
currentSquare[i] = tempSquare[i];
}
///<- Tick 下落 ->///
if (timer > delay)
{
for (int i = 0; i < 4; i++)
{
tempSquare[i] = currentSquare[i];
currentSquare[i].y += 1;
}
if (!hitTest())//如果撞上了
{
for (int i = 0; i < 4; i++)
Field[tempSquare[i].y][tempSquare[i].x] = colorNum;
colorNum = 1 + rand() % 7;
int n = rand() % 7;
for (int i = 0; i < 4; i++ )
{
currentSquare[i].x = Figures[n][i] % 2;
currentSquare[i].y = Figures[n][i] / 2;
}
}
timer = 0;
}
///<- check lines 消行 ->///
int k = STAGE_HEIGHT - 1;
for (int i = STAGE_HEIGHT - 1; i>0;i--)
{
int count = 0;
for (int j= 0; j < STAGE_WIDTH; j++)
{
if (Field[i][j])
count++;
Field[k][j] = Field[i][j];
}
if (count < STAGE_WIDTH)
k--;
}
rotate = 0;
}
void Tetris::Draw(sf::RenderWindow* window)
{
//绘制固定的方块
for (int i = 0; i < STAGE_HEIGHT; i++)
for (int j = 0; j < STAGE_WIDTH; j++)
{
if (Field[i][j] == 0)
continue; //无方块的地方,即空地,则略过
sTiles.setTextureRect(IntRect(Field[i][j] * GRIDSIZE, 0, GRIDSIZE, GRIDSIZE));
sTiles.setPosition(j * GRIDSIZE, i * GRIDSIZE);
sTiles.move(mCornPoint.x, mCornPoint.y); //offset设置偏移量
window->draw(sTiles);
}
//绘制活动的方块
for (int i = 0; i < 4; i++)
{
sTiles.setTextureRect(IntRect(colorNum * GRIDSIZE, 0, GRIDSIZE, GRIDSIZE));
sTiles.setPosition(currentSquare[i].x * GRIDSIZE, currentSquare[i].y * GRIDSIZE);
sTiles.move(mCornPoint.x, mCornPoint.y); //offset设置偏移量
window->draw(sTiles);
}
}
bool Tetris::hitTest()
{
for (int i = 0; i < 4; i++)
if (currentSquare[i].x < 0 || currentSquare[i].x >= STAGE_WIDTH || currentSquare[i].y >= STAGE_HEIGHT)
return false;
else if (Field[currentSquare[i].y][currentSquare[i].x])
return false;
return true;
}