首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >积木游戏

积木游戏
EN

Code Review用户
提问于 2014-11-11 14:21:55
回答 2查看 823关注 0票数 10

上个周末,我一直在研究这个基本的积木游戏,我对此感到非常自豪。我确实认为它可以在许多地方得到改进,例如,由于我设计糟糕的瓷砖加载而导致的性能问题等等。

代码语言:javascript
运行
复制
/** Here are few instructions before you start...
  * IMPORTANT (ON KHANACADEMY ONLY): When you make changes to the code, all tiles will be black.
  * Just hit the restart button to fix that.
  *
  * CONTROLS:
  * MOUSE - Move around the current selected tile.
  * LEFT MOUSE BUTTON - Add a tile to the screen.
  * RIGHT MOUSE BUTTON - Delete a tile from the screen.
  * CONTROL KEY - Change the block type.
  * WASD or LEFT RIGHT DOWN UP - Move around the map.
*/

/* Global program constants */
var CURSOR_FONT = createFont("monospace", 15);
var BACKGROUND_COLOR = color(0, 0, 255);
var HITBOX_COLOR = color(255, 255, 255);
var CLOUD_COLOR = color(255, 255, 255);
var SUN_COLOR1 = color(194, 181, 33);
var SUN_COLOR2 = color(255, 140, 0);
var SUN_WIDTH = 100;
var SUN_HEIGHT = 100;
var TILE_SIZE = 10;
var COLORS = [
    color(180, 120, 20),
    color(20, 150, 20),
    color(100, 100, 100),
    color(240, 200, 10),
    color(5, 44, 117),
    color(255, 255, 255),
    color(110, 70, 10),
    color(10, 210, 20),
];
var TILE_TYPES = [
    "Dirt",
    "Grass",
    "Stone",
    "Sand",
    "Water",
    "Snow",
    "Wood",
    "Leaves",
];

/* Variables concerning map movement */
var movingUp = false;
var movingDown = false;
var movingLeft = false;
var movingRight = false;

/* Array containing cloud data */
var cloudArray = [];

/* Current selected color */
var selectedColor = 0;

/* Array contaning all tile data */
var tileArray = [];

/* Variables controlling the sun's position */
var sunYChange = -0.5;
var SUN_X_POS = 189;
var sunYPos = 200;

/* Render the day and night cycle*/
var renderDayNightCycle = function() {
    noStroke();
    fill(SUN_COLOR2);
    rect(SUN_X_POS, sunYPos, 45, 45);
    fill(SUN_COLOR1);
    rect(SUN_X_POS+5, sunYPos+5, 35, 35);
    sunYPos += sunYChange;
    if(sunYPos <= -50) {
        sunYChange = 0.5;
    }
    if(sunYPos >= 450) {
        sunYChange = -0.5;
    }
};

/* Generate new terrain for the world */
var generateTerrain = function() {
    var c = random(1, 3);
    var blockY = 300;
    for(var x = -1500; x <= 1500; x += TILE_SIZE) {
        tileArray.push([]);
        var rb = round(random(-1, 0));
        tileArray.push({
            xPos: x,
            yPos: blockY+TILE_SIZE*rb,
            colr: COLORS[1],
        });
        if(rb === -1) {
            tileArray.push({
                xPos: x,
                yPos: blockY,
                colr: COLORS[0],
            });
        }
        if(random() >= random()*random()/random()+random()) {
            var m = round(random(2, 6));
            for(var h = blockY-TILE_SIZE; h >= blockY-TILE_SIZE*m; h -= TILE_SIZE) {
                tileArray.push({
                    xPos: x,
                    yPos: h,
                    colr: COLORS[6],
                });
            }
            for(var i = 0; i <= 1; i++) {
                tileArray.push({
                    xPos: x,
                    yPos: blockY-TILE_SIZE*(m+i)-TILE_SIZE,
                    colr: COLORS[7],
                });
            }
            tileArray.push({
                xPos: x+TILE_SIZE,
                yPos: blockY-TILE_SIZE*m-TILE_SIZE,
                colr: COLORS[7]
            });
            tileArray.push({
                xPos: x-TILE_SIZE,
                yPos: blockY-TILE_SIZE*m-TILE_SIZE,
                colr: COLORS[7]
            });
        }
        for(var y = blockY; y <= blockY+TILE_SIZE*round(random(2, 4)); y += TILE_SIZE) {
            tileArray.push({
                xPos: x,
                yPos: y+TILE_SIZE,
                colr: COLORS[0],
            });
        }
        for(var y = blockY+TILE_SIZE*round(c); y <= blockY+TILE_SIZE*random(18, 22); y += TILE_SIZE) {
            tileArray.push({
                xPos: x,
                yPos: y+TILE_SIZE,
                colr: COLORS[2],
            });
        }
        blockY += (ceil(random(-1, 1)/TILE_SIZE)*TILE_SIZE)*round(random(-2, 2));
    }
};

/* Initalize the array of clouds */
var generateClouds = function() {
    for(var i = 0; i <= round(random(2, 12)); i++) {
        cloudArray.push({
            xPos: random(50, 350),
            yPos: random(50, 150),
            w: random(30, 60),
            h: random(10, 20),
        });
    }
};

/* Draw the background */
var drawBackground = function() {
    for(var c = cloudArray.length-1; c >= 0; c--) {
        var cloud = cloudArray[c];
        noStroke();
        fill(CLOUD_COLOR);
        rect(cloud.xPos, cloud.yPos, cloud.w, cloud.h);
        cloud.xPos += random(0.01, 0.09);
        if(cloud.xPos >= 400) {
            cloud.xPos = 0-cloud.w;
        }
    }
};

/* Draw a hitbox over the selected position */
var drawHitbox = function(x, y) {
    noCursor();
    fill(HITBOX_COLOR);
    textFont(CURSOR_FONT);
    text("+", mouseX-1, mouseY+4);
    noFill();
    strokeWeight(1);
    stroke(HITBOX_COLOR);
    rect(x, y, TILE_SIZE, TILE_SIZE);
};

/* Add a block to the screen */
var addBlock = function(x, y) {
    drawHitbox(x, y);
    if(mouseIsPressed && mouseButton === LEFT) {
        if(x >= 20 && y >= 20) {
            tileArray.push({
                xPos: x,
                yPos: y,
                colr: COLORS[selectedColor],
            });
        }
    }
};

/* Delete a block from the screen */
var deleteBlock = function(x, y) {
    drawHitbox(x, y);
    if(mouseIsPressed && mouseButton === RIGHT) {
        for(var t = tileArray.length-1; t >= 0; t--) {
            var tile = tileArray[t];
            if(x === tile.xPos && y === tile.yPos) {
                tileArray.splice(t, 1);
            }
        }
    }
};

/* Render the tileArray */
var renderTiles = function() {
    for(var t = tileArray.length-1; t >= 0; t--) {
        var tile = tileArray[t];
        noStroke();
        fill(tile.colr);
        rect(tile.xPos, tile.yPos, TILE_SIZE, TILE_SIZE);
    }
};

/* Check for specific key actions */
var checkForKeyActions = function() {
    keyPressed = function() {
        if(keyCode === LEFT || keyCode === 65) {
            movingLeft = true;
        }
        if(keyCode === RIGHT || keyCode === 68) {
            movingRight = true;
        }
        if(keyCode === UP || keyCode === 87) {
            movingUp = true;
        }
        if(keyCode === DOWN || keyCode === 83) {
            movingDown = true;
        }
        if(keyCode === CONTROL) {
            selectedColor++;
            if(selectedColor >= COLORS.length) {
                selectedColor = 0;
            }
        }
    };
    keyReleased = function() {
        if(keyCode === LEFT || keyCode === 65) {
            movingLeft = false;
        }
        if(keyCode === RIGHT || keyCode === 68) {
            movingRight = false;
        }
        if(keyCode === UP || keyCode === 87) {
            movingUp = false;
        }
        if(keyCode === DOWN || keyCode === 83) {
            movingDown = false;
        }
    };
    if(movingUp) {
        for(var t = tileArray.length-1; t >= 0; t--) {
            var tile = tileArray[t];
            tile.yPos += TILE_SIZE;
        }
    }
    if(movingDown) {
        for(var t = tileArray.length-1; t >= 0; t--) {
            var tile = tileArray[t];
            tile.yPos -= TILE_SIZE;
        }
    }
    if(movingLeft) {
        for(var t = tileArray.length-1; t >= 0; t--) {
            var tile = tileArray[t];
            tile.xPos += TILE_SIZE;
        }
    }
    if(movingRight) {
        for(var t = tileArray.length-1; t >= 0; t--) {
            var tile = tileArray[t];
            tile.xPos -= TILE_SIZE;
        }
    }
};

/* Draw the current selected tile */
var drawSelectedTile = function() {
    strokeWeight(1.5);
    stroke(255, 255, 255);
    fill(COLORS[selectedColor]);
    rect(5, 5, 15, 15);
    fill(255, 255, 255);
    textFont(CURSOR_FONT);
    text(TILE_TYPES[selectedColor], 25, 17.4); 
};

/* Load the world and clouds before the draw loop begins */
generateTerrain();
generateClouds();

/* Main draw loop */
draw = function() {

    /* Reset the background on each loop */
    background(BACKGROUND_COLOR);

    /* Render the day/night cycle */
    renderDayNightCycle();

    /* Draw the background clouds */
    drawBackground();

    /* Render the tiles */
    renderTiles();

    /* Draw the current selected tile */
    drawSelectedTile();

    /* Check for certain key actions */
    checkForKeyActions();

    /* Check if the user wants to add a block */
    addBlock(ceil(mouseX/TILE_SIZE)*TILE_SIZE-TILE_SIZE, 
             ceil(mouseY/TILE_SIZE)*TILE_SIZE-TILE_SIZE);

    /* Check if the user wants to delete a block */
    deleteBlock(ceil(mouseX/TILE_SIZE)*TILE_SIZE-TILE_SIZE, 
                ceil(mouseY/TILE_SIZE)*TILE_SIZE-TILE_SIZE);

    /* Draw a hitbox over the current selected block */
    drawHitbox(ceil(mouseX/TILE_SIZE)*TILE_SIZE-TILE_SIZE, 
               ceil(mouseY/TILE_SIZE)*TILE_SIZE-TILE_SIZE);
};

我知道还有很多需要改进的地方,那么还有什么可以改进的呢?您可以在这里找到播放它的链接:这里

EN

回答 2

Code Review用户

回答已采纳

发布于 2014-11-11 17:13:40

您的代码比我上次查看它时有了很大的改进。9~10成熟!我确实有一些评论,我只会按它们出现的顺序来讨论它们。

代码语言:javascript
运行
复制
RIGHT MOUSE BUTTON - Delete a tile from the screen.

不是所有的电脑都有鼠标右键。例如,假设有人在使用Mac?

代码语言:javascript
运行
复制
var SUN_COLOR1 = color(194, 181, 33);
var SUN_COLOR2 = color(255, 140, 0);

我认为你最好把这些颜色称为它们是什么,而不是叫它们COLOR1COLOR2backgroundColorforegroundColor在这里会更有意义。

代码语言:javascript
运行
复制
var COLORS = [
    color(180, 120, 20),
    color(20, 150, 20),
    color(100, 100, 100),
    color(240, 200, 10),
    color(5, 44, 117),
    color(255, 255, 255),
    color(110, 70, 10),
    color(10, 210, 20),
];

当第一次遇到这种情况时,读者并不清楚这些颜色将用于什么。我想也许他们会在某个时候被随机分配。如果是这样的话,randomColors将是一个更好的名字。但是,从代码中可以看出,在呈现任何瓷砖时都会使用它们。看起来,selectedColorTILE_TYPES数组和COLORS数组之间有某种关系。不幸的是,从代码中很难理解确切的关系。

这表明,最好是有某种类型的Tile对象,其中包含有关其名称和颜色的信息,以及任何其他必要的重要信息。以面向对象的方式编写Javascript有些困难,因为这些特性没有像它们内置到更传统的语言(如Java )中那样被内置到语言中,但是仍然可以这样做,这将提高代码的可读性。

代码语言:javascript
运行
复制
var CLOUD_COLOR = color(255, 255, 255);
var SUN_COLOR1 = color(194, 181, 33);
var SUN_COLOR2 = color(255, 140, 0);
var movingDown = false;
var movingLeft = false;
var movingRight = false;

选择一种命名风格并坚持下去。不要将ALLCAPITAL变量命名与camelCase混合。尽可能始终如一地编写代码是很重要的。对于Javascript,大多数人建议您执行camelCase中的所有变量。

代码语言:javascript
运行
复制
var generateTerrain = function() {

在这个函数中有很多事情发生,很难精确地跟踪地形是如何产生的。如果您能够理解几个月后查看这段代码时所发生的事情的确切流程,我会感到惊讶。只是我不喜欢的几件:

代码语言:javascript
运行
复制
var c = random(1, 3);
var blockY = 300;
for(var x = -1500; x <= 1500; x += TILE_SIZE) {

所有这些数字似乎都是神奇的数字,应该有描述它们含义的可变名称。

代码语言:javascript
运行
复制
if(random() >= random()*random()/random()+random()) {

我甚至不会试图弄清楚这是在做什么,但它看起来真的很复杂和迟钝。

代码语言:javascript
运行
复制
for(var y = blockY; y <= blockY+TILE_SIZE*round(random(2, 4)); y += TILE_SIZE) {
for(var y = blockY+TILE_SIZE*round(c); y <= blockY+TILE_SIZE*random(18, 22); y += TILE_SIZE) {

再说一遍,不知道这些台词意味着什么。像这样的事情使得我们很难知道用来生成地形的规则。至少应该有一些评论来解释地形生成的各个阶段。然而,我认为,如果您重组功能,使用更多的描述性名称和更清晰的逻辑,这应该是可以理解的,没有很多评论。

代码语言:javascript
运行
复制
/* Draw the background */
var drawBackground = function() {

像上面这样的评论是多余和不必要的。评论通常应该解释为什么你在做某事,而不是你在做什么。这方面的例外是解释一条难以理解的代码行。

代码语言:javascript
运行
复制
draw = function() {

我真的很喜欢把所有的东西都分割成自己的方法。这个方法很容易理解,以后也很容易修改。这是一种很好的做事方法。

票数 6
EN

Code Review用户

发布于 2014-11-11 21:37:15

我喜欢这个项目,

我肯定会创建一个帮助函数来创建这样的瓷砖:

代码语言:javascript
运行
复制
function createTile( x, y, color ){
  tileArray.push({
    x: x,
    y: y,
    color: color,
  });
}

注意,我会将xPos放到x中,因为每个人都正确地解析了x,并且我将colr改为color,因为colr看起来很奇怪。

然后,您的generateTerrain函数变得更加可读性更强,它实际上邀请读者开始与世界世代打交道:

代码语言:javascript
运行
复制
for(var x = -1500; x <= 1500; x += TILE_SIZE) {
    tileArray.push([]);
    var rb = round(random(-1, 0));
    tileArray.push( createTile( x, blockY+TILE_SIZE*rb, COLORS[1] ) );
    if(rb === -1) {
        tileArray.push( createTile( x, blockY, COLORS[0] ) );
    }
//etc etc etc

我建议的另一个改变是通过命名颜色来使颜色更直观:

代码语言:javascript
运行
复制
var tiles = {
  'dirt':  color(180, 120, 20),    //0
  'grass': color(20, 150, 20),     //1
  'stone': color(100, 100, 100),   //2
  'sand': color(240, 200, 10),     //3
  'water': color(5, 44, 117),      //4
  'snow': color(255, 255, 255),    //5
  'wood': color(110, 70, 10),      //6
  'leaves': color(10, 210, 20),    //7
};
var TILE_TYPES = Object.keys( tiles );

然后,在代码中,您可以替换以下颜色语句:

代码语言:javascript
运行
复制
    for(var y = blockY; y <= blockY+TILE_SIZE*round(random(2, 4)); y += TILE_SIZE) {
        tileArray.push( newTile( x, y+TILE_SIZE, tiles.dirt ) );
    }
    for(var y = blockY+TILE_SIZE*round(c); y <= blockY+TILE_SIZE*random(18, 22); y += TILE_SIZE) {
        tileArray.push( newTile( x, y+TILE_SIZE, tiles.stone ) );
    }

至于背景,请查看以下内容:http://cssdeck.com/labs/4ksohwya --可能需要一段时间才能理解背景是如何完成的,但这是非常值得的。

票数 3
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/69495

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档