我正在尝试制作游戏。游戏的目的是在屏幕上移动方块,而不会撞到从屋顶掉下来的雨滴。如何制作它,以便如果其中一个雨滴进入正方形,则正方形返回到画布的开头或x = 0。这是代码:
var canvas = document.getElementById('game');
var ctx = canvas.getContext('2d');
var WIDTH = 1000;
var HEIGHT = 700;
var x = 0;
var y = HEIGHT-20;
var xPos = [0];
var yPos = [0];
var speed = [1];
var rainDrops = 50;
var rectWidth = 20;
var rectHeight = 20;
for (var i = 0; i < rainDrops; i++) {
xPos.push(Math.random()* WIDTH);
yPos.push(0);
speed.push(Math.random() * 5);
}
function rainFall () {
window.requestAnimationFrame(rainFall);
ctx.clearRect(0, 0, WIDTH, HEIGHT);
for (var i = 0; i <rainDrops; i++) {
//Rain
ctx.beginPath();
ctx.arc(xPos[i], yPos[i], 3, 0, 2 * Math.PI);
ctx.fillStyle = 'blue';
ctx.fill();
//Rain movement
yPos[i]+=speed[i];
//Box
ctx.fillStyle = 'red';
ctx.fillRect(x, y, rectWidth, rectWidth);
if (yPos[i] > HEIGHT) {
yPos[i]= 0;
yPos[i]+=speed[0];
}
//This is the part where I need the Help!!!!!!!!!
if (){
x = 0;
}
}
};
//Move Object
function move (e) {
if (e.keyCode === 37) {
ctx.clearRect (0, 0, WIDTH, HEIGHT);
x -=10;
}
if (e.keyCode === 39) {
ctx.clearRect (0, 0, WIDTH, HEIGHT);
x+=10;
}
canvas.width=canvas.width
}
//Lockl Screen
window.addEventListener("keydown", function(e) {
// Lock arrow keys
if( [37,39,].indexOf(e.keyCode) > -1) {
e.preventDefault();
}
}, false);
rainFall();
document.onkeydown = move;
window.addEventListener("load", doFirst, false);
答案 0 :(得分:0)
我从不太确定如何回答这些类型的问题。由于你是初学者,我不想用代码和技术压倒你,但与此同时我也不想给出一个能够延续一些不良技术的答案。
首先,您编写的代码中的简单答案
//This is the part where I need the Help!!!!!!!!!
// the test checks the center of the drop
// if drop is greater than > top of player (y) and (&&)
// drop x greater than > left side of player x and (&&) drop is less than <
// right side of player (x + rectWidth) then drop has hit player
if (yPos[i] > y && xPos[i] > x && xPos[i] < x + rectWidth ){
x = 0; // move player back
}
顺便说一句,你正在为每次降雨画出玩家矩形。你应该把那个绘制函数移到循环之外。
希望我没有让它太混乱,并且添加了很多关于我为什么这样做的评论。
为了帮助保持一切有条理,我将各种元素分成了自己的对象。有player
,rain
和键盘处理程序。这一切都是通过mainLoop
进行协调的,每次调用一次(requestAnimationFrame
)并调用各种函数来完成所需的一切。
player
对象包含与播放器有关的所有数据,以及播放器draw
和update
的功能(更新移动播放器)
rain
对象保存名为rain.drops
的数组中的所有降雨,它具有雨draw
和update
的功能。它还有一些函数来随机化一个drop,并添加新的drop。
为了测试下雨是否已经击中了玩家我是在rain.update
功能(我在哪里下雨)中进行测试的,当雨水冲击玩家时我不知道你想要发生什么,所以我只是重置雨水下降并在点击计数器上加1。
首先检查降雨量drop.y + drop.radius
的底部是否大于播放器顶部if(drop.y + drop.radius >= player.y){
这使得我们不会浪费时间检查玩家上方的雨水。
我在x方向测试雨水。最简单的是测试负面(如果下雨没有击中玩家),因为逻辑稍微简单一些。
如果掉落的右侧位于播放器左侧的左侧,或者(使用||表示或),则放置的左侧位于播放器右侧的右侧而不是放置无法击中玩家。正如我们想要反向条件一样,我们将它包装在一个括号中,放在前面if(! ( ... ) )
测试时间有点长,所以为了便于阅读,我将其分为2行。
// drop is a single rain drop player is the player
if (drop.y + drop.radius >= player.y) {
if ( ! (drop.x + drop.radius < player.x ||
drop.x - drop.radius > player.x + player.width) ) {
// code for player hit by rain in here
}
}
rain.update
函数还会检查雨水是否已经触及画布的底部并重置,如果是的话。
我从问题中复制了您的代码并对其进行了修改。
addEventListener("load",function(){ // you had onload at the bottom after all the code that gets the canvas
// etc. Which kind of makes the on load event pointless. Though not needed
// in this example I have put it in how you can use it for a web page.
// Using onload event lets you put the javascript anywhere in the HTML document
// if you dont use onload you must then only put the javascript after
// the page elements you need eg Canvas.
var canvas = document.getElementById('gameCanvas');
var ctx = canvas.getContext('2d');
ctx.font = "20px arial";
var frameCount = 0; // counts the frames
var WIDTH = canvas.width;
var HEIGHT = canvas.height;
var currentMaxDrops = 5; // rain will increase over time
const numberFramesPerRainIncrease = 60 * 5; // long name says it all. 60 frames is one second.
const maxRainDrops = 150; // max number of rain drops
// set up keyboard handler
addEventListener("keydown", keyEvent);
addEventListener("keyup", keyEvent);
requestAnimationFrame(mainLoop); // request the first frame of the animation (get it all going)
//==========================================================================================
// Setup the keyboard input stuff
const keys = { // list of keyboard keys to listen to by name.
ArrowLeft : false,
ArrowRight : false,
}
function keyEvent(event){ // the key event argument event.code hold the named key.
if(keys[event.code] !== undefined){ // is this a key we want
event.preventDefault(); // prevent default browser action
keys[event.code] = event.type === "keydown"; // true if keydown false if not
}
}
//==========================================================================================
const player = { // object for everything to do with the player
x : 0, // position
y : HEIGHT - 20,
width : 20, // size
height : 20,
speed : 4, // speed per frame
color : "red",
showHit : 0, // when this is > 0 then draw the player blue to indicate a hit.
// This counter is counted down each frame so setting its value
// determins how long to flash the blue
hitCount : 0, // a count of the number of drops that hit the player.
status(){ // uses hit count to get a status string
if(player.hitCount === 0){
return "Dry as a bone.";
}
if(player.hitCount < 5){
return "A little damp.";
}
if(player.hitCount < 15){
return "Starting to get wet.";
}
return "Soaked to the core";
},
draw(){ // draw the player
if(player.showHit > 0){
player.showHit -= 1; // count down show hit
ctx.fillStyle = "blue";
}else{
ctx.fillStyle = player.color;
}
ctx.fillRect(player.x,player.y,player.width,player.height);
},
update(){ // this updates anything to do with the player
// Not sure how you wanted movement. You had it so that you move only when key down events
// so I have done the same
if(keys.ArrowLeft){
player.x -= player.speed; // move to the left
keys.ArrowLeft = false; // turn off the key. If you remove this line then will move left while
// the key is down and stop when the key is up.
if(player.x < 0){ // is the player on or past left side of canvas
player.x = 0; // move player back to zero.
}
}
if(keys.ArrowRight){
player.x += player.speed; // move to the right
keys.ArrowRight = false; // turn off the key. If you remove this line then will move right while
// the key is down and stop when the key is up.
if(player.x + player.width >= WIDTH){ // is the player on or past right side of canvas
player.x = WIDTH - player.width; // move player back to inside the canvas.
}
}
}
}
//==========================================================================================
const rain = { // object to hold everything about rain
numberRainDrops : 50,
drops : [], // an array of rain drops.
randomizeDrop(drop){ // sets a drop to random position etc.
drop.x = Math.random() * WIDTH; // random pos on canvas
drop.y = -10; // move of screen a little so we dont see it just appear
drop.radius = Math.random() *3 + 1; // give the drops a little random size
drop.speed = Math.random() * 4 + 1; // and some speed Dont want 0 speed so add 1
return drop;
},
createDrop(){ // function to create a rain drop and add it to the array of drops
if(rain.drops.length < currentMaxDrops){ // only add if count is below max
rain.drops.push(rain.randomizeDrop({})); // create and push a drop. {} creates an empty object that the function
// randomizeDrop will fill with the starting pos of the drop.
rain.numberRainDrops = rain.drops.length;
}
},
draw(){ // draw all the rain
ctx.beginPath(); // start a new path
ctx.fillStyle = 'blue'; // set the colour
for(var i = 0; i < rain.drops.length; i ++){
var drop = rain.drops[i]; // get the indexed drop
ctx.arc(drop.x, drop.y, drop.radius, 0, 2 * Math.PI);
ctx.closePath(); // stops the drops rendered as one shape
}
ctx.fill(); // now draw all the drops.
},
update(){
for(var i = 0; i < rain.drops.length; i ++){
var drop = rain.drops[i]; // get the indexed drop
drop.y += drop.speed; // move down a bit.
if(drop.y + drop.radius >= player.y){ // is this drop at or below player height
// checks if the drop is to the left or right of the player
// as we want to know if the player is hit we use ! (not)
// Thus the next if statement is if rain is not to the left or to the right then
// it must be on the player.
if(!(drop.x + drop.radius < player.x || // is the rigth side of the drop left of the players left side
drop.x - drop.radius > player.x + player.width)){
// rain has hit the player.
player.hitCount += 1;
player.showHit += 5;
rain.randomizeDrop(drop); // reset this drop.
}
}
if(drop.y > HEIGHT + drop.radius){ // is it off the screen ?
rain.randomizeDrop(drop); // restart the drop
}
}
}
}
function mainLoop () { // main animation loop
requestAnimationFrame(mainLoop); // request next frame (don`t need to specify window as it is the default object)
ctx.clearRect(0, 0, WIDTH, HEIGHT);
frameCount += 1; // count the frames
// when the remainder of frame count and long name var is 0 increase rain drop count
if(frameCount % numberFramesPerRainIncrease === 0){
if(currentMaxDrops < maxRainDrops){
currentMaxDrops += 1;
}
}
rain.createDrop(); // a new drop (if possible) per frame
rain.update(); // move the rain and checks if the player is hit
player.update(); // moves the player if keys are down and check if play hits the side of the canvas
player.draw(); // draw player
rain.draw(); // draw rain after player so its on top.
ctx.fillStyle = "black";
ctx.fillText("Hit " + player.hitCount + " times.",5,20);
ctx.setTransform(0.75,0,0,0.75,5,34); // makes status font 3/4 size and set position to 5 34 so I dont have to work out where to draw the smaller font
ctx.fillText(player.status(),0,0); // the transform set the position so text is just drawn at 0,0
ctx.setTransform(1,0,0,1,0,0); // reset the transform to the default so all other rendering is not effected
};
});
&#13;
canvas {
border : 2px black solid;
}
&#13;
<canvas id="gameCanvas" width=512 height=200></canvas>
&#13;
希望这有用。