效果图展示
代码要点
渲染类
#ifndef Render_hpp
#define Render_hpp
#include <iostream>
#include <sys/time.h>
#include <sys/types.h>
#include <stdlib.h>
#include <ncurses.h>
#include <unistd.h>
class Player;
#include "Piece.hpp"
class Render {
WINDOW *window1, *window2, *scoreWindow, *hintWindow,*hintWindow2;
public:
static const int heightOfGameWindow = 32, widthOfGameWindow = 44;
static const int heightOfHintWindow = 15, widthOfHintWindow = 25;
static const int space = 3;
void initWindow();
void draw(WINDOW* win,Piece & p);
void clear(WINDOW* win,Piece & p);
void end();
friend class Game;
};
#endif /* Render_hpp */
#include "Render.hpp"
void Render::initWindow() {
setlocale(LC_ALL, "");
initscr();
cbreak();
noecho();
curs_set(0);
start_color();
keypad(stdscr,TRUE);
for(int i = 1;i < 8;i++) {
init_pair(i, i, i);
}
// bkgd(COLOR_PAIR(COLOR_WHITE));
refresh();
hintWindow = newwin(heightOfHintWindow,widthOfHintWindow, 0, space);
box(hintWindow,0,0);
mvwprintw(hintWindow,0, 2, "player 1");
mvwprintw(hintWindow,2, 2,"next");
// mvwprintw(hintWindow,11, 2, "score");
wrefresh(hintWindow);
window1 = newwin(heightOfGameWindow, widthOfGameWindow, 0,widthOfHintWindow+2*space);
window2 = newwin(heightOfGameWindow, widthOfGameWindow, 0, getmaxx(window1) + widthOfHintWindow + 3*space);
wattron(window1,COLOR_PAIR(COLOR_WHITE));
wattron(window2, COLOR_PAIR(COLOR_WHITE));
for(int i = 0;i < widthOfGameWindow;i+=2){
mvwprintw(window1,0, i, " ");
mvwprintw(window1,heightOfGameWindow-1, i, " ");
mvwprintw(window2,0,i, " ");
mvwprintw(window2,heightOfGameWindow-1, i, " ");
}
for(int i = 0;i < heightOfGameWindow;i++){
mvwprintw(window1,i, 0, " ");
mvwprintw(window1,i, widthOfGameWindow-2, " ");
mvwprintw(window2,i, 0, " ");
mvwprintw(window2,i, widthOfGameWindow-2, " ");
}
wrefresh(window1);
wrefresh(window2);
wattroff(window1,COLOR_PAIR(COLOR_WHITE));
wattroff(window2, COLOR_PAIR(COLOR_WHITE));
hintWindow2 = newwin(heightOfHintWindow,widthOfHintWindow, 0, 2*getmaxx(window1) + widthOfHintWindow + 4*space);
box(hintWindow2,0,0);
mvwprintw(hintWindow2,0, 2, "player 2");
mvwprintw(hintWindow2,2, 2,"next");
// mvwprintw(hintWindow2,11, 2, "score");
wrefresh(hintWindow2);
}
void Render::end() {
delwin(window1);
delwin(window2);
delwin(hintWindow);
delwin(hintWindow2);
endwin();
}
void Render::draw(WINDOW* win,Piece & p) {
for(int i=0; i<p.sizeHeight;i++){
for(int j=0;j<p.sizeWidth;++j){
wattron(win,COLOR_PAIR(p.color));
if(p.box[i][j]==1){
mvwprintw(win,p.originY+i,p.originX+2*j," ");
}
wattroff(win, COLOR_PAIR(p.color));
}
}
wrefresh(win);
}
void Render::clear(WINDOW* win,Piece & p) {
for(int i=0; i<p.sizeHeight;i++){
for(int j=0;j<p.sizeWidth;j++){
if(p.box[i][j]==1){
mvwprintw(win,p.originY+i,p.originX+2*j," ");
}
}
}
wrefresh(win);
}
/*
如果是特定窗口操作 要调用 wrefresh
如果是stdscr 要调用 refresh
同样,wattron才对mvwprintw有效
attron只对stdscr有效(即 mvprintw)
*/
方块类
#ifndef Piece_hpp
#define Piece_hpp
#include <stdlib.h>
class Piece {
int originX,originY;
int sizeHeight,sizeWidth;
int pieceType; // 0 - 6
int color; // 1-7
int box[4][4];// 移动不需要变这个 旋转才需要变
public:
// //移动
// void moveLeft() {
//
// };
// void moveRight();
// void moveUp();//下移失败时,上移
// void moveDown();
//旋转
// void rotate();
Piece(int type = rand()%7) {
this->setPiece(type,box,sizeWidth,sizeHeight);
color = rand()%7 + 1;
originX = rand()%30 + 1;
originY = 1;
}
void setPiece(int &pieceType, int box[][4],int &size_w,int &size_h);
// void update(
friend class Render;
friend class Player;
friend class Game;
};
#endif /* Piece_hpp */
#include "Piece.hpp"
void Piece::setPiece(int &pieceType, int box[][4],int &size_w,int &size_h)//设置方块形状
// void setPiece(int &pieceType, int box[][4])//设置方块形状
{
int i,j;
for(i=0;i<4;i++)
for(j=0;j<4;j++)
box[i][j]=0; //初始化用来表示方块的数组为0
switch(pieceType)
{
case 0:
size_h=1;
size_w=4;
box[0][0]=1;
box[0][1]=1;
box[0][2]=1;
box[0][3]=1; // @@@@
break;
case 1:
size_h=2;
size_w=3;
box[0][0]=1;
box[1][0]=1;
box[1][1]=1; // @
box[1][2]=1; // @@@
break;
case 2:
size_h=2;
size_w=3;
box[0][2]=1;
box[1][0]=1;
box[1][1]=1; // @
box[1][2]=1; // @@@
break;
case 3:
size_h=2;
size_w=3;
box[0][1]=1;
box[0][2]=1;
box[1][0]=1; // @@
box[1][1]=1; // @@
break;
case 4:
size_h=2;
size_w=3;
box[0][0]=1;
box[0][1]=1;
box[1][1]=1; // @@
box[1][2]=1; // @@
break;
case 5:
size_h=2;
size_w=2;
box[0][0]=1;
box[0][1]=1;
box[1][0]=1; // @@
box[1][1]=1; // @@
break;
case 6:
size_h=2;
size_w=3;
box[0][1]=1;
box[1][0]=1;
box[1][1]=1; // @
box[1][2]=1; // @@@
break;
}
// this->originX = 6;
// this->originY = 1;
}
游戏类
#ifndef Game_hpp
#define Game_hpp
#include "Player.hpp"
#include "Render.hpp"
class Game {
int key;
int tick;
WINDOW *window1, *window2, *scoreWindow, *hintWindow,*hintWindow2;
Render render;
Player* player_pointer[2];
public:
Game() {
tick = 0;
render.initWindow();
player_pointer[0] = new Player;
player_pointer[1] = new Player;
}
~Game() {
delete player_pointer[0];
delete player_pointer[1];
}
int do_tick();
void runloop();
};
#endif /* Game_hpp */
#include "Game.hpp"
int Game::do_tick() {
if (++tick > 30) {
tick = 0;
render.clear(render.window2, player_pointer[1]->currentPiece);
render.clear(render.window1, player_pointer[0]->currentPiece);
player_pointer[1]->currentPiece.originY++;
player_pointer[0]->currentPiece.originY++;
render.draw(render.window2, player_pointer[1]->currentPiece);
render.draw(render.window1, player_pointer[0]->currentPiece);
}
return 1;
}
void Game::runloop() {
// while (do_tick())
while(1){
usleep(10000);
key = getch();
switch (key) {
case KEY_UP:
// player_pointer[1]->currentPiece.rotate();
break;
case KEY_DOWN:
// while(!player_pointer[1]->checkCollision()) {//直接到底
render.clear(render.window2, player_pointer[1]->currentPiece);
player_pointer[1]->movePiece(0);
render.draw(render.window2, player_pointer[1]->currentPiece);
if(player_pointer[1]->checkCollision()) {
player_pointer[1]->currentPiece = player_pointer[1]->nextPiece;
player_pointer[1]->nextPiece = Piece();
}
// }
break;
case KEY_LEFT:
render.clear(render.window2, player_pointer[1]->currentPiece);
player_pointer[1]->movePiece(1);
render.draw(render.window2, player_pointer[1]->currentPiece);
break;
case KEY_RIGHT:
render.clear(render.window2, player_pointer[1]->currentPiece);
player_pointer[1]->movePiece(2);
render.draw(render.window2, player_pointer[1]->currentPiece);
break;
case 'w':
case 'W':
break;
case 's':
case 'S':
render.clear(render.window1, player_pointer[0]->currentPiece);
player_pointer[0]->movePiece(0);
render.draw(render.window1, player_pointer[0]->currentPiece);
break;
case 'a':
case 'A':
render.clear(render.window1, player_pointer[0]->currentPiece);
player_pointer[0]->movePiece(1);
render.draw(render.window1, player_pointer[0]->currentPiece);
break;
case 'd':
case 'D':
render.clear(render.window1, player_pointer[0]->currentPiece);
player_pointer[0]->movePiece(2);
render.draw(render.window1, player_pointer[0]->currentPiece);
break;
default:
break;
}
if() {
render.end();
break;
}
}
}
玩家类
#ifndef Player_hpp
#define Player_hpp
#include "Piece.hpp"
class Player {
int map[32][44];
Piece currentPiece,nextPiece;//当前方块 下一方块
public:
Player() { currentPiece = Piece();nextPiece = Piece();}
bool checkCollision();
void movePiece(int key);
void removeLine();
friend class Game;
};
#endif /* Player_hpp */
#include "Player.hpp"
#include "Piece.hpp"
#include "Render.hpp"
bool Player::checkCollision() {
for(int i=0;i<currentPiece.sizeHeight;i++){
for(int j=0;j<currentPiece.sizeWidth;j++) {
int x = currentPiece.originX;
int y = currentPiece.originY;
if(currentPiece.box[i][j]) {
if(y+i > Render::heightOfGameWindow-3)
return true;
if(x+2*j > Render::widthOfGameWindow-3 || x+i<2)
return true;
if(map[y+i][x+j]==1)
return true ;
}
}
}
return false;
}
void Player::movePiece(int key) {
switch (key) {
case 0: {
//下移
// Render::clear(Render::window2,currentPiece);
currentPiece.originY++;
// Render::draw(Render::window2,currentPiece);
Piece temp = currentPiece;
if(checkCollision()){
// currentPiece.originY--;
for(int i=0;i<temp.sizeHeight;i++)
//把地图上对应的box已占用
for(int j=0;j<temp.sizeWidth;j++)
if(temp.box[i][j]==1)
map[temp.originY-1+i][temp.originX+j]=1;
// currentPiece = Piece(nextPiece.pieceType);
// nextPiece = Piece();
}
break;
}
case 1:
//左移
currentPiece.originX-=2;
if(checkCollision()) {
currentPiece.originX+=2;
}
break;
case 2:
//右移
currentPiece.originX+=2;
if(checkCollision())
currentPiece.originX-=2;
break;
default:
break;
}
}
void Player::removeLine() {
}
依然存在的问题
写了各部分类的代码,但是在整合过程中遇到了困难,正在努力解决中....