- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我做了一个简单的游戏。我们的目标是通过避开激光来维持生命。然而,每次玩家越过激光警告时,它都会消除激光,使其看起来很奇怪。我已经尝试过重新绘制警告,但每次发生这种情况时它都不起作用并且会变得更加错误。
<!DOCTYPE html>
<html>
<head>
<title>
Drift 2
</title>
</head>
<body>
<center>
<h1>Drift 2</h1>
<h2>by Milesman34</h2>
<canvas id="canvas" width="400" height="400"></canvas>
<strong><p id="score">Score</p></strong>
</center>
<script src="https://code.jquery.com/jquery-2.1.0.js"></script>
<script>
//MARK: Set up the canvas + canvas variables and draws the border + background
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var width = canvas.width;
var height = canvas.height;
var blockSize = 20;
var widthInBlocks = width / blockSize;
var heightInBlocks = height / blockSize;
ctx.fillStyle = "rgb(225, 225, 225)";
ctx.fillRect(0, 0, width, height);
//MARK: Defines arrays and variables
var shooterArray = [];
var score = 0;
//MARK: Defines functions
function getRandomFromInterval(interval) {
return Math.floor(Math.random() * interval);
};
//MARK: Defines game over function
var gameEnd = 0;
function gameOver () {
setTimeout (function () {
gameEnd = 1;
clearInterval (scoreEffects);
clearInterval (fireEffects);
ctx.clearRect(blockSize, blockSize, width - (blockSize * 2), height - (blockSize * 2))
ctx.fillStyle = "rgb(225, 225, 225)";
ctx.fillRect(blockSize, blockSize, width - (blockSize * 2), height - (blockSize * 2));
ctx.font = "60px Courier";
ctx.fillStyle = "Black";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.fillText("Game Over", width / 2, height / 2);
}, 149);
};
//MARK: Defines the player
function Player (x, y) {
this.x = x;
this.y = y;
};
//MARK: Defines the function that draws the player
Player.prototype.draw = function () {
ctx.fillStyle = "rgb(185, 185, 185)";
ctx.fillRect(this.x, this.y, blockSize, blockSize);
};
var player = new Player(width / 2, height / 2);
player.draw();
//MARK: Defines the functions that move the player
Player.prototype.moveLeft = function () {
ctx.clearRect(this.x, this.y, blockSize, blockSize);
this.x = this.x - 20;
ctx.fillStyle = "rgb(225, 225, 225)";
ctx.fillRect(this.x + 20, this.y, blockSize, blockSize);
};
Player.prototype.moveRight = function () {
ctx.clearRect(this.x, this.y, blockSize, blockSize);
this.x = this.x + 20;
ctx.fillStyle = "rgb(225, 225, 225)";
ctx.fillRect(this.x - 20, this.y, blockSize, blockSize);
};
Player.prototype.moveUp = function () {
ctx.clearRect(this.x, this.y, blockSize, blockSize);
this.y = this.y - 20;
ctx.fillStyle = "rgb(225, 225, 225)";
ctx.fillRect(this.x, this.y + 20, blockSize, blockSize);
};
Player.prototype.moveDown = function () {
ctx.clearRect(this.x, this.y, blockSize, blockSize);
this.y = this.y + 20;
ctx.fillStyle = "rgb(225, 225, 225)";
ctx.fillRect(this.x, this.y - 20, blockSize, blockSize);
};
Player.prototype.checkWallCollision = function () {
if (this.x === 0 || this.x === width - 20 || this.y === 0 || this.y === height - 20) {
gameOver();
};
};
//MARK: Defines the Shooter
function Shooter (x, y, direction) {
this.x = x;
this.y = y;
if (["left", "right", "up", "down"].indexOf(direction) != -1) {
this.direction = direction;
};
shooterArray.push(this);
};
//MARK: Defines the function that draws the Shooter
Shooter.prototype.draw = function () {
ctx.fillStyle = "rgb(185, 185, 185)";
ctx.fillRect(this.x, this.y, blockSize, blockSize);
};
//MARK: Defines the function that fires the Shooter
var timeoutID = null;
function fireLeftRight(y) {
if (gameEnd === 0) {
ctx.fillStyle = "Red";
ctx.fillRect(blockSize, y, width - (blockSize * 2), blockSize);
if (player.y === y) {
gameOver();
};
};
};
function fireLeftRightWarn(y) {
ctx.fillStyle = "Red";
for (i = 1;i < widthInBlocks - 1;i++) {
ctx.fillRect(i * blockSize + (blockSize / 4), y + (blockSize / 4 * 1.5), blockSize / 2, blockSize / 4);
};
timeoutID2 = setTimeout (function () {
clearTimeout (timeoutID);
timeoutID = setTimeout (fireLeftRight(y), 100);
}, 600);
};
function fireUpDown(x) {
if (gameEnd === 0) {
ctx.fillStyle = "Red";
ctx.fillRect(x, blockSize, blockSize, height - (blockSize * 2));
if (player.x === x) {
gameOver();
};
};
};
function fireUpDownWarn(x) {
ctx.fillStyle = "Red";
for (i = 1;i < heightInBlocks - 1;i++) {
ctx.fillRect(x + (blockSize / 4 * 1.5), i * blockSize + (blockSize / 4), blockSize / 4, blockSize / 2);
};
timeoutID2 = setTimeout (function () {
clearTimeout (timeoutID);
timeoutID = setTimeout (fireUpDown(x))
}, 600);
};
Shooter.prototype.fire = function () {
if (this.direction === "left" || this.direction === "right") {
timeoutID = setTimeout (fireLeftRightWarn(this.y), 1);
} else {
timeoutID = setTimeout (fireUpDownWarn(this.x), 1)
};
};
//MARK: Creates the required shooters
for (i = 1;i < heightInBlocks - 1;i++) {
new Shooter(0, i * blockSize, "right");
};
for (i = 1;i < heightInBlocks - 1;i++) {
new Shooter(width - blockSize, i * blockSize, "left");
};
for (i = 1;i < widthInBlocks - 1;i++) {
new Shooter(i * blockSize, 0, "down");
};
for (i = 1;i < widthInBlocks - 1;i++) {
new Shooter(i * blockSize, height - blockSize, "up")
};
for (i = 0;i < shooterArray.length;i++) {
shooterArray[i].draw();
};
ctx.fillStyle = "rgb(185, 185, 185)";
ctx.fillRect(0, 0, blockSize, blockSize);
ctx.fillRect(width - blockSize, 0, blockSize, blockSize);
ctx.fillRect(0, height - blockSize, blockSize, blockSize);
ctx.fillRect(width - blockSize, height - blockSize, blockSize, blockSize);
//MARK: Draws the score
function drawScore () {
$("#score").text("Score: " + Math.floor(score));
};
//MARK: Convert keycodes to directions
var directions = {
37: "left",
38: "up",
39: "right",
40: "down"
};
//MARK: This is the interval loop
var scoreEffects = setInterval (function () {
score += 0.1;
drawScore();
player.draw();
player.checkWallCollision();
}, 100);
$("body").keyup(function (event) {
if (gameEnd != 1) {
var moveDir = directions[event.keyCode];
if (moveDir === "left") {
player.moveLeft();
} else if (moveDir === "right") {
player.moveRight();
} else if (moveDir === "up") {
player.moveUp();
} else if (moveDir === "down") {
player.moveDown();
};
};
});
var fireEffects = setInterval (function () {
ctx.clearRect(blockSize, blockSize, width - (blockSize * 2), height - (blockSize * 2))
ctx.fillStyle = "rgb(225, 225, 225)";
ctx.fillRect(blockSize, blockSize, width - (blockSize * 2), height - (blockSize * 2));
ctx.fillStyle = "rgb(185, 185, 185)";
ctx.fillRect(0, 0, blockSize, blockSize);
ctx.fillRect(width - blockSize, 0, blockSize, blockSize);
ctx.fillRect(0, height - blockSize, blockSize, blockSize);
ctx.fillRect(width - blockSize, height - blockSize, blockSize, blockSize);
for (i = 0;i < shooterArray.length;i++) {
if (getRandomFromInterval(30) === 0) {
shooterArray[i].fire();
};
};
}, 750);
</script>
最佳答案
此处的工作项目:https://jsfiddle.net/ay7kp7yb/1/
我认为解决这个问题的最佳方法是使用经典模式。这样,游戏中发生的所有事件都需要链接到主循环(请参阅:Game Loop)。
类似于:
while (true)
{
processInputs();
updateObjects();
render();
}
在您的代码中,某些事件与 setTimeout/setInterval 独立发生,“对齐”事件变得非常复杂。
我建议您使用两种组合技术,第一个是将所有事件集中在一个循环(主游戏循环)中,第二个是创建一组状态来控制游戏。
游戏状态:
// game states
var STATE_TITLE_SCREEN = 0;
var STATE_GAME_STARTING = 1;
var STATE_RUNNING = 2;
var STATE_PLAYER_DYING = 3;
var STATE_GAME_OVER_SCREEN = 4;
// current state
var gameState = STATE_TITLE_SCREEN;
// time of the current state
var gameStateTime = 0;
// change the state and reset the time of last state
function setGameState(state) {
gameState = state;
gameStateTime = 0;
}
主循环:
var minIteractionTime = 10;
var mainGameLoop = setInterval (function () {
switch (gameState) {
case STATE_TITLE_SCREEN:
// Title screen (on press space bar, change gameState to STATE_GAME_STARTING)
break;
case STATE_GAME_STARTING:
// Starting game, reset variables, countdown to start, etc...
score = 0.0;
// run the game after 5s
if (gameStateTime>5000)
setGameState(STATE_RUNNING);
break;
case STATE_RUNNING:
score += (0.1/100.0); // 0.1 points after 100 miliseconds
// CLEAR THE SCREEN HERE
drawScore();
player.draw(); // draw the player ONLY here
laserWarning.draw(); // Draws the warnings AFTER draw the player
laserbeam.burn(player); // try to burn the player
break;
case STATE_PLAYER_DYING:
// player dying animation..
// after 5s, change show the game over screen
if (gameStateTime>5000)
setGameState(STATE_GAME_OVER_SCREEN);
break;
case STATE_GAME_OVER_SCREEN:
// draw the game over screen here
// after 5s returns to the title screen
if (gameStateTime>5000)
setGameState(STATE_TITLE_SCREEN);
break;
}
// add the loop time in the gameStateTime variable
gameStateTime += minIteractionTime;
}, minIteractionTime);
激光警告类:
LaserWarning.prototype.draw = function () {
this.warningTime += minIteractionTime;
if (this.warningTime>100) {
// draw the warning only after firsts 100ms
}
if (this.warningTime>=750) { // warning time
// timer reset
this.warningTime = 0;
}
}
激光束类:
Laserbeam.prototype.burn = function (player) {
this.warmingUpTime += minIteractionTime;
if (this.warmingUpTime>=750) { // same time of warning
// draw the laser
// check if burns the player
if (player.checkWallCollision()) {
setGameState(STATE_PLAYER_DYING);
}
}
}
输入迭代:
var gameKeys = {
37: "left",
38: "up",
39: "right",
40: "down",
32: "space"
};
// for all iteractions, check the current state
$("body").keyup(function (event) {
var lastKey = gameKeys[event.keyCode];
switch (gameState) {
case STATE_RUNNING:
if (lastKey === "left") {
player.moveLeft();
} else if (lastKey === "right") {
player.moveRight();
} else if (lastKey === "up") {
player.moveUp();
} else if (lastKey === "down") {
player.moveDown();
};
break;
case STATE_TITLE_SCREEN:
if (lastKey=="space")
setGameState(STATE_GAME_STARTING);
break;
}
});
你应该只在移动玩家时调整定位变量,而不是在新位置重新绘制它,这将发生在 player.draw (); 中,在 STATE_RUNNING 中,在绘制警告之前.
如果用户在 10 毫秒(minIteractionTime)内按向右箭头两次,则玩家将仅被绘制一次!如果您需要更精确,只需减小 minIteractionTime 的值即可。
变量minIteractionTime控制帧速率。
关于javascript - 在我的简单游戏中,玩家总是删除激光警告,而我似乎无法修复它。,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42424503/
我需要将文本放在 中在一个 Div 中,在另一个 Div 中,在另一个 Div 中。所以这是它的样子: #document Change PIN
奇怪的事情发生了。 我有一个基本的 html 代码。 html,头部, body 。(因为我收到了一些反对票,这里是完整的代码) 这是我的CSS: html { backgroun
我正在尝试将 Assets 中的一组图像加载到 UICollectionview 中存在的 ImageView 中,但每当我运行应用程序时它都会显示错误。而且也没有显示图像。 我在ViewDidLoa
我需要根据带参数的 perl 脚本的输出更改一些环境变量。在 tcsh 中,我可以使用别名命令来评估 perl 脚本的输出。 tcsh: alias setsdk 'eval `/localhome/
我使用 Windows 身份验证创建了一个新的 Blazor(服务器端)应用程序,并使用 IIS Express 运行它。它将显示一条消息“Hello Domain\User!”来自右上方的以下 Ra
这是我的方法 void login(Event event);我想知道 Kotlin 中应该如何 最佳答案 在 Kotlin 中通配符运算符是 * 。它指示编译器它是未知的,但一旦知道,就不会有其他类
看下面的代码 for story in book if story.title.length < 140 - var story
我正在尝试用 C 语言学习字符串处理。我写了一个程序,它存储了一些音乐轨道,并帮助用户检查他/她想到的歌曲是否存在于存储的轨道中。这是通过要求用户输入一串字符来完成的。然后程序使用 strstr()
我正在学习 sscanf 并遇到如下格式字符串: sscanf("%[^:]:%[^*=]%*[*=]%n",a,b,&c); 我理解 %[^:] 部分意味着扫描直到遇到 ':' 并将其分配给 a。:
def char_check(x,y): if (str(x) in y or x.find(y) > -1) or (str(y) in x or y.find(x) > -1):
我有一种情况,我想将文本文件中的现有行包含到一个新 block 中。 line 1 line 2 line in block line 3 line 4 应该变成 line 1 line 2 line
我有一个新项目,我正在尝试设置 Django 调试工具栏。首先,我尝试了快速设置,它只涉及将 'debug_toolbar' 添加到我的已安装应用程序列表中。有了这个,当我转到我的根 URL 时,调试
在 Matlab 中,如果我有一个函数 f,例如签名是 f(a,b,c),我可以创建一个只有一个变量 b 的函数,它将使用固定的 a=a1 和 c=c1 调用 f: g = @(b) f(a1, b,
我不明白为什么 ForEach 中的元素之间有多余的垂直间距在 VStack 里面在 ScrollView 里面使用 GeometryReader 时渲染自定义水平分隔线。 Scrol
我想知道,是否有关于何时使用 session 和 cookie 的指南或最佳实践? 什么应该和什么不应该存储在其中?谢谢! 最佳答案 这些文档很好地了解了 session cookie 的安全问题以及
我在 scipy/numpy 中有一个 Nx3 矩阵,我想用它制作一个 3 维条形图,其中 X 轴和 Y 轴由矩阵的第一列和第二列的值、高度确定每个条形的 是矩阵中的第三列,条形的数量由 N 确定。
假设我用两种不同的方式初始化信号量 sem_init(&randomsem,0,1) sem_init(&randomsem,0,0) 现在, sem_wait(&randomsem) 在这两种情况下
我怀疑该值如何存储在“WORD”中,因为 PStr 包含实际输出。? 既然Pstr中存储的是小写到大写的字母,那么在printf中如何将其给出为“WORD”。有人可以吗?解释一下? #include
我有一个 3x3 数组: var my_array = [[0,1,2], [3,4,5], [6,7,8]]; 并想获得它的第一个 2
我意识到您可以使用如下方式轻松检查焦点: var hasFocus = true; $(window).blur(function(){ hasFocus = false; }); $(win
我是一名优秀的程序员,十分优秀!