如何使用香草Javascript从播放器中提取子弹?

时间:2019-03-20 02:25:12

标签: javascript html html5 function html5-canvas

我正在尝试制作一种向上滚动的街机射击游戏。我一直陷在如何从玩家向敌人将要向上弹子弹的问题上。我正在使用setInterval在玩家所在的位置重复射击动作,但是子弹只会跟随战斗机重新设置间隔,每次玩家移动指定的距离。

有帮助吗?

此刻是我的代码。

谢谢。

var project, ctx, img, img2, width, height, mid, midh, startPx, startPy, audio,interval,bulletStartPx,bulletStartPy;
var score = 0;

function setUp() {
 project = document.getElementById("project");
 ctx = project.getContext("2d");
 width = 505;
 height = 900;
 mid = width/2;
 midh = height/2;
 startPx = width/2-30;
 startPy = height-150;

 audio = new Audio("bgm.mp3");
 audio.play();

 img = new Image();
 img2 = new Image();
 img.src = "bg.png";
 img2.src = "fighterjet.png"
 img.onload = function(){
   ctx.shadowColor = "#ffffff";
   ctx.shadowBlur = 15;
   ctx.drawImage(img, 0, 0);
   ctx.drawImage(img2, startPx, startPy)
 }
 
 window.addEventListener("keydown", checkKeyPress);
}

function drawObject(x, y) {
  ctx.drawImage(img2, startPx, startPy)
}

function checkKeyPress(event) {
  if (event.keyCode == "87") {//W(UP)
    ctx.clearRect(0,0,width,height);
    if (startPy >= 20) {
    startPy -= 20;
    }
    ctx.drawImage(img, 0, 0);
    ctx.drawImage(img2, startPx, startPy)
  } else if (event.keyCode == "83") {//S(DOWN)
    ctx.clearRect(0,0,width,height);
    if (startPy <= 785) {
    startPy += 20;
    }
    ctx.drawImage(img, 0, 0);
    ctx.drawImage(img2, startPx, startPy)
  } else if (event.keyCode == "65") {//A(LEFT)
    ctx.clearRect(0,0,width,height);
    if (startPx >= 0) {
    startPx -= 20;
    }
    ctx.drawImage(img, 0, 0);
    ctx.drawImage(img2, startPx, startPy)
  } else if (event.keyCode == "68") {//D(RIGHT)
    ctx.clearRect(0,0,width,height);
    if (startPx <= 410) {
    startPx += 20;
    }
    ctx.drawImage(img, 0, 0);
    ctx.drawImage(img2, startPx, startPy)
  } else if (event.keyCode == "72") {
    for (let i = 0; i < 6; i++) {
      bullets();
  }
}
}

function bullets() {
  return setInterval(function(){
          bulletStartPx = startPx+48;
          bulletStartPy = startPy-30;
          ctx.fillStyle = "gold"
          ctx.beginPath();
          ctx.arc(bulletStartPx,bulletStartPy,5,0,2*Math.PI);
          ctx.fill();
          score += 25; }, 100);
}

function GameOver(){
  document.getElementById('bm').pause();
  ctx.font = '30px Courier New'
  ctx.filltext('GAME OVER', mid, midh)
  ctx.filltext('Your score was: '+score, mid, midh+40)
}

function showScore(){
  ctx.fillStyle = '#ff0000'
  ctx.font = '18px Courier New'
  ctx.text(score, width-10, 15)
}






/*
function bullet(){
  this.x = startPx;
	this.y = startPy - 10;

  this.draw = function() {
    ctx.fillStyle = "#b20808";
    ctx.shadowColor = "#b20808";
    ctx.shadowBlur = 15;
    this.y -= bulletSpeed;
    ctx.fillRect(this.x, this.y, 2, 8);
  }
}

function fireGun(){
if (event.keyCode == "32") {
   bullet();
   }
}*/
<!DOCTYPE html>
<html>
  <head>
    <title>Project</title>
    <meta charset="utf-8">
    <script src="project.js" type="text/javascript" defer></script>
  </head>
  <body>
    <h1>Arcade Shooter</h1>
    <fieldset>
    <legend><h2>Instructions:</h2></legend>
    <h3>Press W, A, S, D to Move</h3>
    <h3>Press Space Bar to Fire</h3>
    <h3>Goal: Survive as long as you can!</h3>
    </fieldset>
    <br>
    <canvas id="project" style="border-style: solid" width=505 height=900 ></canvas>
    <br>
      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
      <input id="start" type="button" value="START THE GAME" onclick="setUp()" style="width: 300px">
  </body>
</html>

2 个答案:

答案 0 :(得分:0)

1)您需要重新定义全局变量,以便跟踪所有内容:

[assembly: ExportRenderer(typeof(ListView), typeof(MyLVRenderer))]
public class MyLVRenderer : ListViewRenderer
    {
        //UITableViewSource originalSource;

        protected override void OnElementChanged(ElementChangedEventArgs<ListView> e)
        {
            base.OnElementChanged(e);

            UITableViewSource originalSource = (UIKit.UITableViewSource)Control.Source;
            Control.Source = new MyLVSource(originalSource);

        }
    }

    public class MyLVSource : UITableViewSource
    {
        UITableViewSource originalSource;

        public MyLVSource(UITableViewSource origSource)
        {
            originalSource = origSource;
        }

        public override nint RowsInSection(UITableView tableview, nint section)
        {
            return originalSource.RowsInSection(tableview, section);
        }

        public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
        {
            return originalSource.GetCell(tableView, indexPath);
        }

        public override nfloat GetHeightForFooter(UITableView tableView, nint section)
        {
            return originalSource.GetHeightForFooter(tableView, section);
        }

        public override nfloat GetHeightForRow(UITableView tableView, NSIndexPath indexPath)
        {
            nfloat origHeight = originalSource.GetHeightForRow(tableView, indexPath);

            // calculate your own row height here
            return origHeight + (indexPath.Row +1) * 10;
        }                
    }

2)仅检查checkKeyPress(event)函数中的动作,包括fireGun动作:

var gameData = {
    interval: null, // Controls the refresh
    redrawRequired: false, // Flag
    allBullets: [], // Moving bullets
    defaultBulletSpeed: 20 // Bullet speed
}

3)这是定义子弹对象和firegun()函数的方法:

function checkKeyPress(event) {
    if (event.keyCode == "87") {//87 W(UP)
        if (startPy >= 20) {
            startPy -= 20;
            gameData.redrawRequired = true;
        }
    } else if (event.keyCode == "83") {//83 S(DOWN)
        if (startPy <= 785) {
            startPy += 20;
            gameData.redrawRequired = true;
        }
    } else if (event.keyCode == "65") {//65 A(LEFT)
        if (startPx >= 0) {
            startPx -= 20;
            gameData.redrawRequired = true;
        }
    } else if (event.keyCode == "68") {//68 D(RIGHT)
        if (startPx <= 410) {
            startPx += 20;
            gameData.redrawRequired = true;
        }
    } else if (event.keyCode == "72") { // 72 SPACEBAR ?? Actually H
        fireGun();
    }
}

4)然后使用一个主要功能(refreshGame)和另一个功能检查是否有要更新的项目符号(refreshBullets),决定何时重新绘制画布:

function Bullet() {
    // Object defining a bullet.
    this.x = startPx;
    this.y = startPy - 10;
    this.bulletSpeed = gameData.defaultBulletSpeed;
}

Bullet.prototype.draw = function () {
    // Draws the bullet on canvas...
    ctx.fillStyle = "#b20808";
    ctx.shadowColor = "#b20808";
    ctx.shadowBlur = 15;
    ctx.fillRect(this.x, this.y, 2, 8);
}

Bullet.prototype.move = function () {
    // Moves the bullet...
    this.y = this.y - this.bulletSpeed;
}


function fireGun() {
    var newBullet = new Bullet();
    gameData.allBullets.push(newBullet);
}

5)最后,您初始化整个过程,包括setUp()函数中的setInterval:

function refreshBullets() {
    var i = 0;
    var currentBullet;
    // Start by eliminating bullets out of the screen...
    while (i < gameData.allBullets.length) {
        currentBullet = gameData.allBullets[i];
        if (currentBullet.y < -10) {
            gameData.allBullets.splice(i, 1); // Remove the bullet outside of the screen.
        } else {
            currentBullet.move();
            gameData.redrawRequired = true;
            i += 1; // Next bullet...
        }
    }
}


function refreshGame() {
    refreshBullets();
    if (gameData.redrawRequired) {
        ctx.clearRect(0,0,width,height);
        ctx.drawImage(img, 0, 0, width, height);
        ctx.drawImage(img2, startPx, startPy);

        for (var i = 0; i < gameData.allBullets.length; i++) {
            gameData.allBullets[i].draw();
        }
    }
    gameData.redrawRequired = false;
}

注意:

  • 由于性能问题,使用setInterval的canvas方法被认为是一种不好的方法。尝试搜索“使用画布刷新JavaScript间隔”,还有其他方法可以解决该问题。 refreshRequired变量/属性只是一个占位符,用于解释解决方法。实际上,您必须不断重绘场景,因为背景,目标和威胁将在飞机下方移动,并且您将在此过程中更新得分。

  • 在编写代码之前,您应该设计游戏,其目标,角色,控制方式,界限,水平是什么。......纸和笔是一个好的开始。问题是,当您开始手工编写代码时,问自己的那一刻就会卡住,我该如何使子弹与目标相撞?如果我可以改用导弹呢?最后,由于您试图在创建另一个问题的同时解决一个问题,因此您的代码将变得很繁重且占用大量处理器资源……只是一个建议;)

答案 1 :(得分:0)

您不想每次发射子弹时都使用setInterval。 您想在整个游戏中使用一个setInterval,以便在每个游戏对象上调用更新或绘制功能。 例如

var game={
  //this is a list of items in the game I want to move around or do stuff
  //nothing there yet
  objects:[]
}
//this is a bullet object which can be created calling new bullet()
function Bullet(){
   //IM CHEATING HERE. DON'T DRAW TO THE DOM FOR GAMES
   //this is just a shortcut instead of drawing on a canvas
  this.object=document.createElement('div');
  this.object.style.width="10px";
  this.object.style.height="10px";
  this.object.style.position='absolute';
  this.object.style.top="100px";
  this.object.style.backgroundColor='red';
  document.body.appendChild(this.object)
  ///
  //these hold the bullet's current location on screen
  this.x=100;
  this.y=100;

  //this is the update function that gets called every frame
  this.update=function(){
     //I'm updating the bullet's y position.
    this.y-=10;
    if(this.y>0){
     
      //don't draw to the dom like this. use canvas like you were doing.
      this.object.style.top=this.y+"px";
    }
  }
}

//now let's add a bullet to the game
game.objects.push(new bullet());

//the function that updates each of our objects
function runGame(){
  for(var i=0;i<game.objects.length;i++){
      game.objects[i].update();
  }
}
//start the game
setInterval(runGame, 1000)

注意:请勿像这样在DOM上绘制。像以前一样使用画布。我只是将dom用作演示的快捷方式