以下为源代码,不知是否有错,敬请谅解。
#include "codingtang.h"
#include<cstdlib>
#include<ctime>
using namespace std;
#define RESOLUTION_W 1024
#define RESOLUTION_H 768
#define INVALID_BLOCK_ID -1
const int blockCount = 10;
const int tileSize = 32;
const int screenTileWidth = RESOLUTION_W / tileSize;
const int screenTileHeight = RESOLUTION_H / tileSize;
Window window;
enum blockType { BEDROCK, GRASS, DIRT, STONE, DIAMOND, COAL, IRON, GOLD, REDSTONE, EMERALD };
typedef struct Block {
int id;
} Block;
void renderTexture(string &texture, int w, int h, int x, int y, Rect &clip) {
Rect dest;
dest.x = x;
dest.y = y;
dest.h = h;
dest.w = w;
window.drawImageEx(texture.c_str(), &clip, &dest);
}
struct MCWorld {
string blockSprites;
Rect blockClips[blockCount];
Block map[screenTileWidth][screenTileHeight];
void init() {
// Load Spritesheet sections into SDL_Rects
blockSprites = "blocks.png";
// Load each block in the sheet into a SDL_Rect clip
int x = 0;
int y = 0;
for(int i=0;i<blockCount;i++) {
blockClips[i].x = x;
blockClips[i].y = y;
blockClips[i].w = 16;
blockClips[i].h = 16;
// if last block on the X axis (for a 64x64 spritesheet)
if(x == 48) {
// Move to the first block on the row below
x = 0;
y += 16;
} else {
// Move to the next block on the current row
x += 16;
}
}
// init map tiles to NULL
for(int tileY=0;tileY<screenTileHeight;tileY++) {
for(int tileX=0;tileX<screenTileWidth;tileX++) {
map[tileX][tileY].id = INVALID_BLOCK_ID;
}
}
}
void create() {
const int bedrockLayerStart = screenTileHeight-1; // 1 layer bedrock
const int stoneLayerStart = bedrockLayerStart-3; // 3 layers stone
const int dirtLayerStart = stoneLayerStart-1; // 1 layer dirt
const int grassLayerStart = dirtLayerStart-1; // 1 layer grass
blockType id;
for(int y=grassLayerStart;y<screenTileHeight;y++) {
switch(y) {
case grassLayerStart:
id = blockType::GRASS;
break;
case dirtLayerStart:
id = blockType::DIRT;
break;
case stoneLayerStart:
id = blockType::STONE;
break;
case bedrockLayerStart:
id = blockType::BEDROCK;
break;
default:
break;
}
for(int x=0;x<screenTileWidth;x++) {
map[x][y].id = id;
}
}
}
void draw() {
// Sky
window.drawColor(128, 192, 255, 255);
window.fillRect(0, 0, RESOLUTION_W, RESOLUTION_H);
// Blocks
for(int y=0;y<screenTileHeight;y++) {
for(int x=0;x<screenTileWidth;x++) {
if(map[x][y].id != INVALID_BLOCK_ID) {
// if grass/dirt is above grass, make the grass below dirt
if(map[x][y].id == blockType::GRASS && y-1 >= 0) {
if(map[x][y-1].id != INVALID_BLOCK_ID) {
map[x][y].id = blockType::DIRT;
}
}
// render
if(map[x][y].id != INVALID_BLOCK_ID)
renderTexture(blockSprites, tileSize, tileSize, x*tileSize, y*tileSize, blockClips[map[x][y].id]);
}
}
}
}
// X and Y of where the player is trying to go
bool collision(int x, int y) {
return map[x][y].id != INVALID_BLOCK_ID || map[x][y+1].id != INVALID_BLOCK_ID;
}
void destroyBlock(int x, int y) {
if(y != screenTileHeight-1) {
map[x][y].id = INVALID_BLOCK_ID;
}
}
void createBlock(int id, int x, int y, int playerX, int playerY) {
// Player collision
if((y == playerY || y == playerY+1) && x == playerX) {
return;
}
// Check if block to build upon
for(int xOffset=-1;xOffset<=1;xOffset++) {
if(map[x+xOffset][y].id != INVALID_BLOCK_ID) {
if(map[x][y].id == INVALID_BLOCK_ID) {
map[x][y].id = id;
}
}
}
for(int yOffset=-1;yOffset<=1;yOffset++) {
if(map[x][y+yOffset].id != INVALID_BLOCK_ID) {
if(map[x][y].id == INVALID_BLOCK_ID) {
map[x][y].id = id;
}
}
}
}
};
struct MCPlayer {
string playerSprites;
Rect playerClips[3];
int playerForward, playerRight, playerLeft, currentSprite;
int x;
int y;
// Load spritesheet into SDL_Rects
void init() {
playerSprites = "player.png";
// Load each player sprite in the sheet into a SDL_Rect clip
for(int i=0;i<3;i++) {
playerClips[i].x = i*16;
playerClips[i].y = 0;
playerClips[i].w = 16;
playerClips[i].h = 32;
}
playerForward = 0;
playerRight = 1;
playerLeft = 2;
}
// Create player at (20, 22)
void create() {
x = (screenTileWidth/2);
y = (screenTileHeight-8);
currentSprite = playerForward;
}
void draw() {
renderTexture(playerSprites, tileSize, tileSize*2, x*tileSize, y*tileSize, playerClips[currentSprite]);
}
void moveUp() {
if(y-1 >= 0) {
y -= 1;
if(currentSprite != playerForward) resetSprite();
}
}
void moveDown() {
if(y+1 <= screenTileHeight-3) {
y += 1;
if(currentSprite != playerForward) resetSprite();
}
}
void moveLeft() {
if(x-1 >= 0) {
x -= 1;
if(currentSprite != playerLeft) currentSprite = playerLeft;
}
}
void moveRight() {
if(x+1 <= screenTileWidth-1) {
x += 1;
if(currentSprite != playerRight) currentSprite = playerRight;
} else {
x = 0;
}
}
void resetSprite() {
currentSprite = playerForward;
}
};
struct MCInventory {
string inventorySprites;
Rect hotbar, hbOverlay;
blockType hbSelection;
void init() {
inventorySprites = "inventory.png";
hotbar.x = 0;
hotbar.y = 0;
hotbar.w = 160;
hotbar.h = 16;
hbOverlay.x = 160;
hbOverlay.y = 0;
hbOverlay.h = 16;
hbOverlay.w = 16;
hbSelection = blockType::BEDROCK;
}
void create() {
}
void draw() {
renderTexture(inventorySprites, tileSize*10, tileSize, (RESOLUTION_W/2)-(tileSize*5), 0, hotbar);
renderTexture(inventorySprites, tileSize, tileSize, (RESOLUTION_W/2)-(tileSize*5) + (tileSize*hbSelection), 0, hbOverlay);
return;
}
};
int main(){
window = createWindow(RESOLUTION_W,RESOLUTION_H); // 1024 * 768
MCWorld world;
MCPlayer player;
MCInventory inventory;
world.init();
player.init();
inventory.init();
world.create();
player.create();
inventory.create();
world.draw();
player.draw();
inventory.draw();
bool quit = false;
bool falling = false;
int fallTimer = 0;
while(!quit) {
Event e;
if(pollEvent(&e)) {
// Keyboard Events
if(e.type == CDT_KEYDOWN) {
switch(e.keyCode) {
case KEY_SPACE:
if(!falling) {
if(!world.collision(player.x, player.y-1)) {
player.moveUp();
falling = true;
}
}
break;
case CDT_KEY_d:
if(!world.collision(player.x+1, player.y)) {
player.moveRight();
if(!world.collision(player.x, player.y+1))
falling = true;
}
break;
case CDT_KEY_a:
if(!world.collision(player.x-1, player.y)) {
player.moveLeft();
if(!world.collision(player.x, player.y+1))
falling = true;
}
break;
case CDT_KEY_1:
inventory.hbSelection = blockType::BEDROCK;
break;
case CDT_KEY_2:
inventory.hbSelection = blockType::GRASS;
break;
case CDT_KEY_3:
inventory.hbSelection = blockType::DIRT;
break;
case CDT_KEY_4:
inventory.hbSelection = blockType::STONE;
break;
case CDT_KEY_5:
inventory.hbSelection = blockType::DIAMOND;
break;
case CDT_KEY_6:
inventory.hbSelection = blockType::COAL;
break;
case CDT_KEY_7:
inventory.hbSelection = blockType::IRON;
break;
case CDT_KEY_8:
inventory.hbSelection = blockType::GOLD;
break;
case CDT_KEY_9:
inventory.hbSelection = blockType::REDSTONE;
break;
case CDT_KEY_0:
inventory.hbSelection = blockType::EMERALD;
break;
}
}
if(e.type == CDT_KEY_UP) {
if(e.keyCode == CDT_KEY_a || e.keyCode == CDT_KEY_d) {
player.resetSprite();
}
}
// Mouse Events
if(e.type == CDT_MOUSEBUTTONDOWN) {
int x = (e.button.x - (e.button.x % tileSize))/tileSize;
int y = (e.button.y - (e.button.y % tileSize))/tileSize;
if(e.button.button == CDT_BUTTON_RIGHT) {
world.destroyBlock(x, y);
}
if(e.button.button == CDT_BUTTON_LEFT) {
world.createBlock(inventory.hbSelection, x, y, player.x, player.y);
}
}
}
if(falling) {
fallTimer++;
if(fallTimer == 20) {
if(!world.collision(player.x, player.y+1)) {
player.moveDown();
fallTimer = 0;
} else {
falling = false;
fallTimer = 0;
}
}
}
// Rerender
world.draw();
player.draw();
inventory.draw();
window.present();
// Don't set cpu on fire
sleep(1);
}
return 0;
}
————————————————
版权声明:本文为CSDN博主「m0_751885https://blog.csdn.net/m0_75188587/article/details/128047874