别踩白块儿 这… 还用开发吗?
别人已经制作了呀
触屏版本多的是
是挺多的 但是 你见过按键版本的嘛?
没见过吧 这就是需要开发出来 ,
进入项目需求环节
别踩白块儿 顾名思义:不要踩白色方块 踩了你就失败 到达一定的分数或者到达一定的时间会加快速度 直到踩了白块就认定失败
开发语言:C/C++ (优选C++)
实现效果
别踩白块儿 主框架类声明
#pragma once
#undef UNICODE
#undef _UNICODE
#include"Games.h"
const int GameInterfaceWidth = 640;
const int GameInterfaceHeight = 480;
using GameState = enum class DontTapTheWhiteTileState;
//别踩白块儿
class DontTapTheWhiteTile{
public:
DontTapTheWhiteTile();
//初始化属性
void initAttribute(Games* Gamesfirst, Games* GamesSecond);
//运行游戏
void RunGame(void);
~DontTapTheWhiteTile();
private:
//初始化游戏场景
void initGameInterface();
//初始化游戏
void initGeme();
//绘制游戏界面外框
void DrawOuterFrame();
//绘制游戏界面
void DrawGameInterfaces();
//处理游戏按键
void HandlesPlayerButtons(const char& key);
//延时
void TimeDelay();
Games* m_GamesFirst;
Games* m_GamesSecond;
GameState m_GamesFirstState;
GameState m_GamesSecondState;
};
//绘制游戏场景
class DrawGameInterface {
public:
DrawGameInterface( Games &theGame, GameState& gameState);
void operator()();
private:
GameState&m_GameState;
Games& m_theGame;
};
class OutText {
public:
OutText(Pos& Pos, int x ,int y ,const char &c);
void operator()();
private:
Pos& m_Pos;
Pos m_pos;
const char &m_C;
};
class OutTextByStr {
public:
OutTextByStr(Pos& Pos, int x, int y, const char *str);
void operator()();
private:
Pos& m_Pos;
Pos m_pos;
const char *m_Str;
};
/ 绘制矩形
class DrawRectangle {
public:
DrawRectangle(Pos& Pos, int x1, int y1, int x2, int y2);
void operator()();
private:
Pos& m_Pos;
Pos m_pos[2];
};
/// 绘制有边框矩形
class DrawFillRectangle {
public:
DrawFillRectangle(Pos& Pos, int x1, int y1, int x2, int y2);
void operator()();
private:
Pos& m_Pos;
Pos m_pos[2];
};
// 绘制有边框矩形
class DrawSolidRectangle {
public:
DrawSolidRectangle(Pos& Pos, int x1, int y1, int x2, int y2);
void operator()();
private:
Pos& m_Pos;
Pos m_pos[2];
};
//绘制游戏界面外框
class DrawOuterFrames {
public:
DrawOuterFrames(Games& Games);
void operator()();
private:
Games& m_Games;
};
//处理游戏者按键
class HandlesPlayerButton {
public:
HandlesPlayerButton(GameState& GameState, Games& theGame, const char& Key);
void operator()();
private:
GameState& m_GameState;
Games& m_theGame;
const char& m_key;
};
class GameReset {
public:
GameReset(GameState& GameState, Games& theGame);
void operator()();
private:
GameState& m_GameState;
Games& m_theGame;
};
//绘制游戏界面中的一行任务
class DrawRowTask {
public:
DrawRowTask(int& baseY, int& TaskId, Games& Games);
void operator()();
private:
int& m_baseY;
int& m_TaskId;
Games& m_theGame;
static const size_t ColorSize = 4;
static const COLORREF LineColor = 0xe9dbd6;
static const COLORREF TextColor = WHITE;
static const char* const start;
int Textwidth;
int TextHeight;
};
// 绘制通过游戏后的界面
class DrawPass {
public:
DrawPass(Games& Games);
void operator()();
private:
Games& m_theGame;
static const COLORREF FillColor = GREEN;
static const int TextY = 100;
static const COLORREF TextColor = WHITE;
};
//绘制失败界面
class DrawFail {
public:
DrawFail(Games& theGame, GameState& GameState);
void operator()();
private:
Games& m_theGame;
GameState& m_GameState;
static const int zero = 0;
};
//延时
class TimeDelayS {
public:
TimeDelayS(int &ms);
void operator()();
static clock_t oldclock;
int &m_ms;
};
别踩白块儿 主框架类实现
#include "DontTapTheWhiteTile.h"
#include"Games.h"
#include
#include
#include
DontTapTheWhiteTile::DontTapTheWhiteTile(){
initGameInterface();
}
void DontTapTheWhiteTile::initAttribute(Games* Gamesfirst, Games* GamesSecond){
this->m_GamesFirst= Gamesfirst;
this->m_GamesSecond = GamesSecond;
initGeme();
}
void DontTapTheWhiteTile::RunGame(void){
const char ESc =27;
char ch = 0;
while (ch!=ESc){
while (_kbhit()){
ch = _getch();
HandlesPlayerButtons(ch);
}
DrawGameInterfaces();
TimeDelay();
}
}
DontTapTheWhiteTile::~DontTapTheWhiteTile(){
closegraph();
}
void DontTapTheWhiteTile::initGameInterface(){
initgraph(GameInterfaceWidth, GameInterfaceHeight);
const DWORD bkcolor = (DWORD)0x01bbfb;
srand((unsigned int)time(nullptr));
setbkcolor(bkcolor);
cleardevice();
}
void DontTapTheWhiteTile::initGeme(){
this->m_GamesFirstState = GameState::GameStart;
this->m_GamesSecondState = GameState::GameStart;
this->DrawOuterFrame();
}
void DontTapTheWhiteTile::DrawOuterFrame(){
DrawOuterFrames(*this->m_GamesFirst)();
DrawOuterFrames(*this->m_GamesSecond)();
}
void DontTapTheWhiteTile::DrawGameInterfaces(){
DrawGameInterface(*this->m_GamesFirst, this->m_GamesFirstState)();
DrawGameInterface(*this->m_GamesSecond, this->m_GamesSecondState)();
}
void DontTapTheWhiteTile::HandlesPlayerButtons(const char &key){
HandlesPlayerButton(this->m_GamesFirstState, *this->m_GamesFirst, key)();
HandlesPlayerButton(this->m_GamesSecondState, *this->m_GamesSecond, key)();
}
void DontTapTheWhiteTile::TimeDelay(){
static int Ms = 16;
TimeDelayS t(Ms);
t();
}
DrawGameInterface::DrawGameInterface( Games& theGame, GameState& gameState) : m_theGame(theGame), m_GameState(gameState) {
}
void DrawGameInterface::operator()() {
GameState& GameState = m_GameState;
Games& theGame = m_theGame;
int& nextTaskY = m_theGame.m_nextTaskY;
Task& TaskId = m_theGame.m_TaskId;
DrawPass DrawPass(theGame);
DrawFail DrawFail(theGame, GameState);
switch (GameState){
case GameState::GamePassani: {
if (nextTaskY == 100) {
GameState = GameState::GamePass;
DrawPass();
break;
}
}
case GameState::GameStart:
case GameState::GameRun: {
if (nextTaskY == 100) {
return;
}
nextTaskY -= (nextTaskY - 100 + 9) / 10;
int rowy = nextTaskY;
int TaskIt = TaskId;
DrawRowTask DrawRowTask(rowy, TaskIt, theGame);
do{
rowy -= 100;
--TaskIt;
DrawRowTask();
} while (rowy > 0);
rowy = nextTaskY;
TaskIt = TaskId;
do {
DrawRowTask();
rowy += 100;
++TaskIt;
} while (rowy < 400);
break;
}
case GameState::GameFailani:
DrawFail();
break;
case GameState::GamePass:
case GameState::GameFAIL:
break;
}
}
OutText::OutText(Pos& Pos, int x, int y, const char &c) :m_Pos(Pos), m_pos{ x,y }, m_C(c){
}
void OutText::operator()(){
int&& x = this->m_Pos.x + this->m_pos.x;
int&& y = this->m_Pos.y + this->m_pos.y;
outtextxy(x, y, m_C);
}
OutTextByStr::OutTextByStr(Pos& Pos, int x, int y, const char* str):m_Pos(Pos), m_pos{ x,y }, m_Str(str){
}
void OutTextByStr::operator()(){
int&& x = this->m_Pos.x + this->m_pos.x;
int&& y = this->m_Pos.y + this->m_pos.y;
outtextxy(x, y, m_Str);
}
DrawRectangle::DrawRectangle(Pos& Pos, int x1, int y1, int x2, int y2) :m_Pos(Pos), m_pos{ {x1,y1},{x2,y2} }{
}
void DrawRectangle::operator()(){
int &&left = this->m_Pos.x + this->m_pos[false].x;
int&& top = this->m_Pos.y + this->m_pos[false].y;
int &&right = this->m_Pos.x + this->m_pos[true].x;
int &&bottom = this->m_Pos.y + this->m_pos[true].y;
rectangle(left, top, right, bottom);
}
DrawFillRectangle::DrawFillRectangle(Pos& Pos, int x1, int y1, int x2, int y2) :m_Pos(Pos), m_pos{ {x1,y1},{x2,y2} }{
}
void DrawFillRectangle::operator()() {
int&& left = this->m_Pos.x + this->m_pos[false].x;
int&& top = this->m_Pos.y + this->m_pos[false].y;
int&& right = this->m_Pos.x + this->m_pos[true].x;
int&& bottom = this->m_Pos.y + this->m_pos[true].y;
fillrectangle(left, top, right, bottom);
}
DrawSolidRectangle::DrawSolidRectangle(Pos& Pos, int x1, int y1, int x2, int y2) :m_Pos(Pos), m_pos{ {x1,y1},{x2,y2} }{
}
void DrawSolidRectangle::operator()() {
int&& left = this->m_Pos.x + this->m_pos[false].x;
int&& top = this->m_Pos.y + this->m_pos[false].y;
int&& right = this->m_Pos.x + this->m_pos[true].x;
int&& bottom = this->m_Pos.y + this->m_pos[true].y;
fillrectangle(left, top, right, bottom);
}
DrawOuterFrames::DrawOuterFrames(Games& Games):m_Games(Games){
}
void DrawOuterFrames::operator()(){
const DWORD linecolor = 0xfb9700;
setlinecolor(linecolor);
auto& pos = this->m_Games.m_pos;
DrawRectangle(pos, 0, 0, 243, 464)();
const DWORD fillcolor = 0xeca549;
setfillcolor(fillcolor);
settextcolor(BLACK);
settextstyle(16, 0, "Verdana");
setbkmode(TRANSPARENT);
DrawSolidRectangle(pos, 2, 2, 241, 21)();
int TextWidth = textwidth(this->m_Games.m_Name);
int CalculateTextX = (244 - TextWidth) / 2;
OutTextByStr(pos, CalculateTextX, 4, this->m_Games.m_Name)();
DrawSolidRectangle(pos, 2, 23, 241, 42)();
char temp[150];
sprintf_s(temp, "最好记录:%.3f 秒", this->m_Games.m_bestTime);
OutTextByStr(pos, 10, 26, temp)();
DrawSolidRectangle(pos, 2, 445, 241, 462)();
for (size_t i = 0; i < 4; i++){
OutText(pos, 2 + i * 60 + 26, 446, this->m_Games.m_key[i])();
}
}
HandlesPlayerButton::HandlesPlayerButton(GameState& GameState, Games& theGame, const char& Key):m_GameState(GameState),m_theGame(theGame), m_key(Key){
}
void HandlesPlayerButton::operator()(){
Games& theGame = this->m_theGame;
const char*& Keys = theGame.m_key;
const char& Key = this->m_key;
GameState &GameState = this->m_GameState;
auto& Task = theGame.m_Task;
auto& TaskId = theGame.m_TaskId;;
auto& nextTaskY = theGame.m_nextTaskY;
auto& bestTime = theGame.m_bestTime;
auto& lastTime = theGame.m_lastTime;
auto& beginClock = theGame.m_beginClock;
auto& failErrorKey = theGame.m_failErrorKey;
bool flag;
switch (GameState){
case GameState::GameStart:
flag = strchr(Keys, Key);
if (flag){
beginClock = clock();
GameState = GameState::GameRun;
}
case GameState::GameRun: {
const char* dest = strchr(Keys, Key);
flag = dest;
if (flag) {
byte pos = dest - Keys;
if (pos == Task[TaskId]) {
++TaskId;
nextTaskY += 100;
if (TaskId == MaxTask) {
clock_t&& c = clock();
lastTime = ((float)(clock() - beginClock)) / CLOCKS_PER_SEC;
if (lastTime < bestTime) {
bestTime = lastTime;
}
TaskId++;
nextTaskY += 100;
GameState = GameState::GamePassani;
}
}else{
failErrorKey = pos;
GameState = GameState::GameFailani;
}
}
break;
}
case GameState::GamePassani:
case GameState::GameFailani:
break;
case GameState::GameFAIL:
flag = strchr(Keys, Key);
if (flag){
GameReset(GameState, theGame)();
}
default:
break;
}
}
GameReset::GameReset(GameState& GameState, Games& theGame):m_GameState(GameState),m_theGame(theGame){
}
void GameReset::operator()(){
Games& theGame = this->m_theGame;
GameState& GameState = this->m_GameState;
GameState = GameState::GameStart;
theGame.init();
DrawOuterFrames DrawOuterFrame(theGame);
DrawOuterFrame();
}
DrawRowTask::DrawRowTask(int& baseY, int& TaskId, Games& Games):m_baseY(baseY),m_TaskId(TaskId),m_theGame(Games){
Textwidth = textwidth(start);
TextHeight = textheight(start);
}
const char* const DrawRowTask::start = "开始";
void DrawRowTask::operator()(){
int First = this->m_baseY;
int&& Second = First + 99;
if (First < 0) {
First = 0;
}
if (Second > 399) {
Second = 399;
}
auto & GamesTaskId = this->m_theGame.m_TaskId;
int& TaskId = this->m_TaskId;
const auto& theGameTask = this->m_theGame.m_Task;
auto& theGamePos = this->m_theGame.m_pos;
COLORREF color[ColorSize];
if (TaskId < 0) {
for (size_t i = 0; i < ColorSize; i++){
color[i] = YELLOW;
}
}else if (TaskId > MaxTask) {
for (size_t i = 0; i < ColorSize; i++) {
color[i] = GREEN;
}
}else {
for (size_t i = 0; i < ColorSize; i++){
color[i] = WHITE;
}
color[theGameTask[TaskId]] = (TaskId < GamesTaskId) ? LIGHTGRAY : BLACK;
}
setlinecolor(LineColor);
for (size_t i = 0; i < ColorSize; i++) {
setfillcolor(color[i]);
DrawFillRectangle(theGamePos, 2 + i * 60, 44 + 399 - First, 2 + i * 60 + 59, 44 + 399 - Second)();
}
if (TaskId==0 && GamesTaskId==0){
int TextX = 2 + theGameTask[TaskId] * 60 + (60 - Textwidth) / 2;
int TextY = 44 + 399 - 99 - First + (100 - TextHeight) / 2;
settextcolor(TextColor);
settextstyle(16, 0, "Verdana");
OutTextByStr(theGamePos, TextX, TextY, start)();
}
}
DrawPass::DrawPass(Games& Games):m_theGame(Games){
}
void DrawPass::operator()(){
auto& theGamePos = this->m_theGame.m_pos;
auto& theGamelastTime = this->m_theGame.m_lastTime;
setfillcolor(FillColor);
DrawSolidRectangle(theGamePos, 2, 44, 241, 443)();
settextcolor(TextColor);
settextstyle(16, 0, "Verdana");
const char OK[] = "成功";
int Textwidth = textwidth(OK);
int TextX = (244 - Textwidth) / 2;
OutTextByStr(theGamePos, TextX, TextY, OK)();
char temp[100];
sprintf_s(temp, "成绩:%.3f 秒", theGamelastTime);
Textwidth = textwidth(temp);
TextX = (244 - Textwidth) / 2;
OutTextByStr(theGamePos, TextX, 200, temp)();
sprintf_s(temp, "速度:%.3f 秒", MaxTask / theGamelastTime);
Textwidth = textwidth(temp);
TextX = (244 - Textwidth) / 2;
OutTextByStr(theGamePos, TextX, 200, temp)();
const char (hint)[21] = "按任意控制键重新开始";
settextstyle(16, 0, "Verdana");
Textwidth = textwidth(hint);
TextX = (244 - Textwidth) / 2;
OutTextByStr(theGamePos, TextX, 400, hint)();
}
DrawFail::DrawFail(Games& theGame, GameState& GameState):m_theGame(theGame) , m_GameState(GameState) {
}
void DrawFail::operator()(){
auto& theGame = this->m_theGame;
auto& theGameFailFrame = theGame.m_failFrame;
auto& theGameFailRect = theGame.m_failRect;
const int counts = MaxTask + 10;
auto& theGamePos = theGame.m_pos;
auto& theGameFailRectLeft = theGameFailRect.left;
auto& theGameFailRectRight = theGameFailRect.right;
auto& theGameFailRectTop = theGameFailRect.top;
auto& theGameFailRectBottom = theGameFailRect.bottom;
if (theGameFailFrame == zero){
auto& theGameFailkeys = theGame.m_failErrorKey;
auto& theGameNextTaskY = theGame.m_nextTaskY;
theGameFailRectLeft = 3 + theGameFailkeys * 60;
theGameFailRectRight = theGameFailRect.left + 57;
theGameFailRectBottom = theGameNextTaskY + 1;
theGameFailRectTop = theGameNextTaskY + 98;
if (theGameFailRectTop > 398) {
theGameFailRectTop = 398;
}
theGameFailRectBottom = 44 + 398 - theGameFailRectBottom;
theGameFailRectTop = 44 + 398 - theGameFailRectTop;
}
if (theGameFailFrame < counts) {
const auto fillcolor = ((theGameFailFrame / 6) % 2 == 0) ? RED : LIGHTRED;
setfillcolor(fillcolor);
DrawSolidRectangle(theGamePos, theGameFailRectLeft, theGameFailRectBottom, theGameFailRectRight, theGameFailRectTop)();
++theGameFailFrame;
}else {
auto& theGameState = this->m_GameState;
theGameState = GameState::GameFAIL;
const auto fillcolor = RED;
auto& theGamembestTime = theGame.m_bestTime;
setfillcolor(fillcolor);
DrawSolidRectangle(theGamePos, 2, 44, 241, 443)();
const auto textcolor = WHITE;
settextcolor(textcolor);
settextstyle(60, 0, "Verdana");
const char *No = "失败";
int Textwidth = textwidth(No);
int TextX = (244 - Textwidth) / 2;
int TextY = 100;
OutTextByStr(theGamePos, TextX, TextY, No)();
settextstyle(20, 0, "Verdana");
char temp[100];
sprintf_s(temp, "历史最好成绩:%.3f 秒", theGamembestTime);
Textwidth = textwidth(temp);
TextX = (244 - Textwidth) / 2;
TextY = 200;
OutTextByStr(theGamePos, TextX, TextY, temp)();
const char(hint)[21] = "按任意控制键重新开始";
settextstyle(16, 0, "Verdana");
Textwidth = textwidth(hint);
TextX = (244 - Textwidth) / 2;
TextY = 400;
OutTextByStr(theGamePos, TextX, TextY, hint)();
}
}
clock_t TimeDelayS::oldclock = clock();
TimeDelayS::TimeDelayS(int& ms):m_ms(ms)
{
}
void TimeDelayS::operator()(){
oldclock += this->m_ms * CLOCKS_PER_SEC / 1000;
if (clock() > oldclock){
oldclock = clock();
}else {
while (clock()< oldclock){
Sleep(1);
}
}
}
main.cpp 使用别踩白块儿主框架类和游戏者类
#include"DontTapTheWhiteTile.h"
#include"Games.h"
int main(void) {
DontTapTheWhiteTile d;
Games game1("罗小黑", "asdf", { 38,8 });
Games game2("罗小白", "jkl;", { 358,8 });
d.initAttribute(&game1, &game2);
d.RunGame();
return 0;
}
游戏者类声明
#pragma once
#include
#include
#include"DontTapTheWhiteTileState.h"
using Task = unsigned char;
const size_t MaxTask = 50;
const int DefaultNextTaskY = 200;
struct Pos{
int x;
int y;
};
class Games {
Games();
public:
Games(const char* name, const char* key, Pos Pos);
void init();
const char* m_Name;
const char* m_key;
Pos m_pos;
Task m_Task[MaxTask];
Task m_TaskId;
int m_nextTaskY;
clock_t m_beginClock; // 游戏开始的时钟计数
float m_bestTime; // 最佳纪录的完成时间
float m_lastTime; // 最后一次的完成时间
byte m_failErrorKey; // 按错的键的序号(值为 0、1、2、3)
RECT m_failRect; // 按错的键的区域
int m_failFrame; // 失败后的动画的帧计数
};
游戏者类实现
#include "Games.h"
#include
Games::Games(){
init();
}
Games::Games(const char* name, const char* key, Pos Pos):Games(){
this->m_Name = name;
this->m_key = key;
this->m_pos = Pos;
}
void Games::init(){
for (Task& value : this->m_Task) {
const int RandNum = rand();
value = (RandNum % 4);
}
this->m_TaskId = 0;
this->m_nextTaskY = DefaultNextTaskY;
this->m_failFrame = 0;
this->m_bestTime = 99.0f;
this->m_failRect = {};
}
游戏状态枚举类
#pragma once
using GameState = enum class DontTapTheWhiteTileState;
//别踩白块儿 游戏状态
enum class DontTapTheWhiteTileState {
GameStart, //游戏开始状态
GameRun, //游戏运行状态
GamePassani, //游戏通过的动画状态
GamePass, //游戏通过状态
GameFailani, //游戏失败的动画状态
GameFAIL //游戏失败状态
};
类的封装能力,仿函数的实际应用 图形库接口了解