画布游戏拍摄和选择问题+视口

时间:2017-07-21 22:01:06

标签: javascript canvas

我在画布游戏中拍摄时遇到了问题。当我向目标(敌人)射击子弹并且前方没有其他敌人时,子弹向右移动,但当敌人在玩家面前并且他们正在直接射向目标时,当遇到第一个敌人时子弹消失。我希望子弹直接攻击敌人,我不知道如何实现目标。

  1. 其他问题是我制作的十字准线,它可以选择多个敌人,但我希望能够只选择一个敌人。任何想法如何处理?我几乎可以肯定,这是一个小问题。

  2. 我想制作视口,但是当我从互联网上实现某些东西时,它只是不起作用,而且,我不仅仅是在问,我真的很努力地制作这个视口,也就像解决我提到的其他问题。我希望你能解决一些这些问题,谢谢。
  3. 
    
    var ctx = $("#canvas")[0].getContext('2d'),
        cHeight = canvas.height = 800,
        cWidth = canvas.width = 1300,
        canvasOffset = $('#canvas').offset(),
        offsetX = canvasOffset.left,
        offsetY = canvasOffset.top,
        frameCounter = 0,
        enemyList = [],
        bulletList = [],
        spawningEnemies_FLAG = true,
        isLeftMouseButtonHeld_FLAG = false,
        isAnyEnemySelected_FLAG = false,
        cursors = ['default', 'pointer'],
        enemiesOnMap = 10;
    
    
    ctx.font = '22px Arial';
    
    
    var sharedBehaviour = {
    
        x: (cWidth / 2) - (cWidth / 8) + randomNumberFromRange(1, (cWidth / 8)),
        y: (cHeight / 2) - (cHeight / 8) + randomNumberFromRange(1, (cHeight / 8)),
        id: undefined,
        type: 'entity',
        width: 15,
        height: 15,
        fillColor: '#E15258',
        targetX: null,
        targetY: null,
        bulletSpeed: 1,
        aimAngle: null,
        circleRadius: null,
        circleColor: 'black',
        circleWidth: 1,
    
        // Statistics
        hp: 10,
        shield: 0,
        speed: 1,
    
        update( type ) {
            if( type === 'player' ) {
                enemyList.forEach( enemy => {
                    if ( enemy.isMouseOver() ) {
                        if( isLeftMouseButtonHeld_FLAG ) {
                            player.targetX = player.targetY = null;
                        }
                    }
                });
            }
            // if there is target
            if( this.targetX !== null ) {
                // Find out distance to target
                var distanceX = this.targetX - this.x; // distance on X axis
                var distanceY = this.targetY - this.y; // distance on Y axis
                var distanceToTarget = Math.sqrt( distanceX*distanceX + distanceY*distanceY ); // distance
    
                // If distance is smaller or equal speed, then just set position
                if( distanceToTarget <= this.speed ) {
                    this.x = this.targetX;
                    this.y = this.targetY;
                    // Then reset
                    this.targetX = this.targetY = null;
                } else { // If distance is bigger than speed, so we want to move with speed
                    distanceX = distanceX / distanceToTarget;
                    distanceY = distanceY / distanceToTarget;
                    distanceX = distanceX * this.speed;
                    distanceY = distanceY * this.speed;
                    this.x += distanceX;
                    this.y += distanceY;
                }
            }
        },
        draw( ) {
            drawRect( this.x - this.width/2,
                      this.y - this.height/2,
                      this.width,
                      this.height, 
                      this.fillColor );
        },
        highlight( ) {
            crosshair( this.x - this.width/2, this.y - this.height/2, this.width, this.height, 
                       20, 25, // radius1, radius2
                       6, // endLineWidth
                       1, 2, // circle1Width, circle2Width
                       2, 2, 2, 2, // topLineWidth, rightLineWidth, bottomLineWidth, leftLineWidth
                       '#E15258', '#E15258', // circle1Color, circle2Color
                       '#C25975' ); // linesColor
        },
        isColliding( entity ) {
            // Collision: rect to rect
            return testCollisionRectRect( this, entity );
        },
        drawCircle( ) {
            drawCircle( this.x, this.y, this.circleRadius, this.circleWidth, this.circleColor );
        }
    
    };
    
    
    
    var player = Object.assign({}, sharedBehaviour, { 
        x: cWidth/2 - 10,
        y: cHeight/2 - 10,
        id: 980722,
        type: 'player',
        width: 20,
        height: 20,
        fillColor: '#82d877',
        bulletSpeed: 1,
        circleRadius: 200,
        circleColor: 'black',
        circleWidth: 1,
        pressingC: false,
    
        // Player stats
        name: 'player1',
        pd: 0,
        hp: 10,
        speed: 2.5
    });
    
    
    
    function createEnemy( x, y, id, width, height, fillColor, speed, type ) {
    
        var newEnemy = Object.assign({}, sharedBehaviour, {
            x,
            y,
            id,
            width,
            height,
            type,
            fillColor,
            mouseX: null,
            mouseY: null,
            isHighlighted: false,
            isClicked: false,
            circleRadius: 50,
            circleColor: 'red',
            circleWidth: 1,
            
            // Statistics
            hp: 100,
            shield: 0,
            speed,
    
            setTarget( entity ) {
                this.targetX = entity.x + randomNumberFromRange(-50, 50);
                this.targetY = entity.y + randomNumberFromRange(-50, 50);
            },
            isOnPlayer( val ) {
                // Check if enemy is on player
                var distanceX = player.x - this.x;
                var distanceY = player.y - this.y;
                return Math.sqrt( distanceX*distanceX + distanceY*distanceY ) < val;
            },
            isMouseOver( ) {
                return (this.mouseX + this.width/2 >= this.x && this.mouseX + this.width/2 <= this.x + this.width && this.mouseY + this.height/2 >= this.y && this.mouseY + this.height/2 <= this.y + this.height);
            }
        });
    
        enemyList.push( newEnemy );
    
    }
    
    
    function createBullet( actor ) {
        var newBullet = Object.assign({}, sharedBehaviour, {
            x: actor.x,
            y: actor.y,
            height: 7,
            width: 7,
            aimAngle: actor.aimAngle,
            fillColor: 'green',
            spdX: Math.cos(actor.aimAngle/180*Math.PI)*8,
            spdY: Math.sin(actor.aimAngle/180*Math.PI)*8,
            update ( ) {
                this.x += this.spdX;
                this.y += this.spdY;
            }
        });
    
        bulletList.push( newBullet );
    }
    
    
    function newGame( ) {
        // Reset all to its defaults
        player.hp = 10;
        frameCounter = 0;
        enemyList = [];
        bulletList = [];
        spawningEnemies_FLAG = true;
        isLeftMouseButtonHeld_FLAG = false;
    
        // Spawning enemies
        for( i=0; i < randomNumberFromRange(15, 25); i++ ) {
            createEnemy( randomNumberFromRange(0, cWidth), randomNumberFromRange(0, cHeight), 'str' + (i+1), randomNumberFromRange(12, 18), randomNumberFromRange(12, 18), 'red', 1, 's' );
            createEnemy( randomNumberFromRange(0, cWidth), randomNumberFromRange(0, cHeight), 'lor' + (i+1), randomNumberFromRange(10, 16), randomNumberFromRange(10, 16), 'lightblue', 1.5, 'l' ); 
        }
    
        requestAnimationFrame(update);
    }
    
    
    
    
    
    function update( ) {
        frameCounter++;
        ctx.clearRect(0,0,cWidth,cHeight);
    
        enemyList.forEach( enemy => {
            enemy.update();
        });
    
        // Update bullet position and remove if goes out of canvas
        bulletList.forEach( bullet => {
            bullet.update();
            if ( bullet.x < 0 || bullet.x > cWidth || bullet.y < 0 || bullet.y > cHeight) {
                bulletList.remove(bullet);
            }
        });
    
        player.update('player');
    
        enemyList.forEach( enemy => {
    
            if( enemy.isHighlighted ) {
                if( enemy.isMouseOver() ) {
                    enemy.draw();
                    enemy.highlight();
                } else {
                    enemy.draw()
                }
            } else {
                enemy.draw();
            }
    
            if( enemy.isClicked ) {
                enemy.draw();
                enemy.highlight();
            } else {
                enemy.draw();
            }
    
    
            if ( Math.random() < ( 1 / 15 ) ) { // 1 in 25 chance to look for player about once every 0.25 sec
                if ( enemy.isOnPlayer( player.circleRadius ) ) {
                    if ( ! (enemy.isOnPlayer( 50 )) ) {
                        enemy.setTarget( player );
                    }
                }
            }
    
            if ( Math.random() < ( 1 / 800 )) { // 1 in 500 chance to look for player about once every 5 sec
                if ( ! (enemy.isOnPlayer( player.circleRadius )) ) {
                    enemy.setTarget( enemy );
                }
            }
    
            if ( enemy.isOnPlayer(player.circleRadius/4 ) ) {
                enemy.targetX = enemy.targetY = null; // Reset enemy target
            }
    
            // If bullet has collision with enemy, rcemove both and add reward
            bulletList.forEach( bullet => {
                if ( testCollisionRectRect(enemy, bullet) ) {
    
                     if( enemy.isClicked ) {
                    enemy.hp -= 5;
                    bulletList.remove(bullet);
                     if ( enemy.hp <= 0 ) {
                        enemyList.remove(enemy);
    
                    }
                }
                   
                }
            });
    
        });
    
        bulletList.forEach( bullet => {
            bullet.draw();
        });
    
        player.draw();
        player.drawCircle();
    
        if ( frameCounter % 500 === 0 && spawningEnemies_FLAG ) {
            createEnemy( randomNumberFromRange(0, cWidth), randomNumberFromRange(0, cHeight), 'str' + (i+1), randomNumberFromRange(12, 18), randomNumberFromRange(12, 18), 'red', 1, 's' );
            createEnemy( randomNumberFromRange(0, cWidth), randomNumberFromRange(0, cHeight), 'lor' + (i+1), randomNumberFromRange(10, 16), randomNumberFromRange(10, 16), 'lightblue', 1.5, 'l' );
        }
    
        if ( enemyList.length === enemiesOnMap ) {
            spawningEnemies_FLAG = false;
        } else {
            spawningEnemies_FLAG = true;
        }
    
        ctx.fillText(player.hp + " hp", 10, 25);
        ctx.fillText('Map 1', cWidth-70, 25);
        requestAnimationFrame(update);
    }
    
    
    document.onmousedown = function( mouse ) {
        isLeftMouseButtonHeld_FLAG = true;
        setPlayerTargetAndCheckAvailableArea( mouse );
    }
    
    document.onmouseup = function( mouse ) {
        isLeftMouseButtonHeld_FLAG = false;
    }
    
    document.onmousemove = function( mouse ) {
        if ( isLeftMouseButtonHeld_FLAG ) {
            setPlayerTargetAndCheckAvailableArea( mouse );
        }
        
        var mouseX = mouse.clientX - document.getElementById('canvas').getBoundingClientRect().left;
        var mouseY = mouse.clientY - document.getElementById('canvas').getBoundingClientRect().top;
    
        var newX, newY;
    
        enemyList.forEach( enemy => {
            if( enemy.isClicked ) {
                isAnyEnemySelected_FLAG = true;
                newX = enemy.x;
                newY = enemy.y;
            }
        });
    
        if( isAnyEnemySelected_FLAG ) {
            newX -= player.x;
            newY -= player.y;
            player.aimAngle = Math.atan2(newY, newX) / Math.PI * 180;
        } else {
            isAnyEnemySelected_FLAG = false;
            mouseX -= player.x;
            mouseY -= player.y;
            player.aimAngle = Math.atan2(mouseY, mouseX) / Math.PI * 180;
        }
    
    
        var mousexX = parseInt(mouse.clientX - offsetX);
        var mouseyY = parseInt(mouse.clientY - offsetY);
    
        var currentCursor = 0;
    
        enemyList.forEach( enemy => {
            enemy.mouseX = mousexX;
            enemy.mouseY = mouseyY;
    
            if(enemy.isMouseOver()) {
                currentCursor = 1;
                if(enemy.isClicked) {
                    enemy.isHighlighted = false;
                } else {
                    enemy.isHighlighted = true;
                }
            } else {
                enemy.isHighlighted = false;
            }
    
        });
    
        canvas.style.cursor = cursors[currentCursor];
    }
    
    document.onclick = function( mouse ) {
        var mousexX = parseInt(mouse.clientX - offsetX);
        var mouseyY = parseInt(mouse.clientY - offsetY);
    
        enemyList.forEach( enemy => {
            enemy.mouseX = mousexX;
            enemy.mouseY = mouseyY;
    
            if(enemy.isMouseOver()) {
                if(enemy.isHighlighted) {
                    enemy.isHighlighted = false;
                    enemy.isClicked = true;
                } else {
                    enemy.isClicked = false;
                }
            } else {
                enemy.isClicked = false;
            }
        });
    }
    
    
    document.onkeydown = function ( key ) {
        switch(key.keyCode) {
            case 67:
                player.pressingC = true;
                break;
        }
    }
    
    document.onkeyup = function ( key ) {
        switch(key.keyCode) {
            case 67:
                player.pressingC = false;
                if( isAnyEnemySelected_FLAG ) {
                    createBullet( player );
                }
                break;
        }
    }
    
    
    
    function setPlayerTargetAndCheckAvailableArea ( mouse ) {
        player.targetX = mouse.clientX - document.getElementById('canvas').getBoundingClientRect().left;
        player.targetY = mouse.clientY - document.getElementById('canvas').getBoundingClientRect().top;
    
        if (player.targetX < player.width/2) {
            player.targetX = player.width/2; 
        }
    
        if (player.targetX > cWidth - player.width/2) { 
            player.targetX = cWidth - player.width/2 
        }
    
        if (player.targetY < player.height/2) { 
            player.targetY = player.height/2; 
        }
    
        if (player.targetY > cHeight - player.height/2) { 
            player.targetY = cHeight - player.height/2 
        }
    }
    
    
    
    function randomNumberFromRange( min, max ) {
        return Math.floor(Math.random() * (max - min + 1)) + min;
    }
    
    function testCollisionRectRect( rectangle1, rectangle2 ) {
        return rectangle1.x - rectangle1.width/2 <= rectangle2.x - rectangle2.width/2 + rectangle2.width
            && rectangle2.x - rectangle2.width/2 <= rectangle1.x - rectangle1.width/2 + rectangle1.width
            && rectangle1.y - rectangle1.height/2 <= rectangle2.y - rectangle2.height/2 + rectangle2.height
            && rectangle2.y - rectangle2.height/2 <= rectangle1.y - rectangle1.height/2 + rectangle1.height;
    }
    
    Array.prototype.remove = function() {
        var what, a = arguments, L = a.length, ax;
        while (L && this.length) {
            what = a[--L];
            while ((ax = this.indexOf(what)) !== -1) {
                this.splice(ax, 1);
            }
        }
        return this;
    }; // Function to pop specific element drom array by value
    
    
    function crosshair( x, y, width, height, radius1, radius2, endLineWidth, circle1Width, circle2Width, topLineWidth, rightLineWidth, bottomLineWidth, leftLineWidth, circle1Color, circle2Color, linesColor) {
        drawCircle(x + width/2, y + height/2, radius1, circle1Width, circle1Color);
        drawCircle(x + width/2, y + height/2, radius2, circle2Width, circle2Color);
        drawLine(x + radius1 + width/2, y + height/2, x + (radius2 + endLineWidth) + width/2, y + height/2, linesColor, leftLineWidth);
        drawLine(x - radius1 + width/2, y + height/2, x - (radius2 + endLineWidth) + width/2, y + height/2, linesColor, rightLineWidth);
        drawLine(x + width/2, y + radius1 + height/2, x + width/2, y + (radius2 + endLineWidth) + height/2, linesColor, bottomLineWidth);
        drawLine(x + width/2, y - radius1 + height/2, x + width/2, y - (radius2 + endLineWidth) + height/2, linesColor, topLineWidth);
    }
    
    function drawLine( startX, startY, endX, endY, color, width ) {
        ctx.save();
        ctx.strokeStyle = color;
        ctx.lineWidth = width;
        ctx.beginPath();
        ctx.moveTo(startX,startY);
        ctx.lineTo(endX,endY);
        ctx.stroke();
        ctx.restore();
    }
    
    function drawCircle( x, y, radius, lineWidth, strokeColor ) {
        ctx.save();
        ctx.beginPath();
        ctx.arc( x, y, radius, 0, 2 * Math.PI, false);
        ctx.lineWidth = lineWidth;
        ctx.strokeStyle = strokeColor;
        ctx.stroke();
        ctx.restore();
    }
    
    function drawBorder( x, y, width, height, lineWidth, strokeColor ) {
        ctx.save();
        ctx.lineWidth = lineWidth;
        ctx.strokeStyle = strokeColor;
        ctx.strokeRect( x, y, width, height);
        ctx.restore();
    }
    
    function drawRect( x, y, width, height, fillColor ) {
        ctx.save();
        ctx.fillStyle = fillColor;
        ctx.fillRect( x, y, width, height );
        ctx.restore();
    }
    
    
    
    
    
    newGame();
    &#13;
    canvas {
        border: 1px solid black;
        background-color: white;
    }
    &#13;
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> 
    <canvas id="canvas" width="1300" height="800"></canvas>
    &#13;
    &#13;
    &#13;

0 个答案:

没有答案