gpt4 book ai didi

javascript - 在我的简单游戏中,玩家总是删除激光警告,而我似乎无法修复它。

转载 作者:太空宇宙 更新时间:2023-11-04 15:59:05 24 4
gpt4 key购买 nike

我做了一个简单的游戏。我们的目标是通过避开激光来维持生命。然而,每次玩家越过激光警告时,它都会消除激光,使其看起来很奇怪。我已经尝试过重新绘制警告,但每次发生这种情况时它都不起作用并且会变得更加错误。

<!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/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com