我正在尝试使用jquery,javascript,html和css制作一个简单的游戏.我一直陷入碰撞检测.
码:
var map = [
[0,1,0,0,0,1,0,0,],
[0,1,0,0,0,1,0,0,],
[0,1,0,0,0,1,0,0,],
[0,1,1,1,0,1,0,0,],
[0,0,0,0,0,0,0,2,]
];
function DrawMap() {
for(var i=0; i < map.length; i++){
for(var j=0; j < map[i].length; j++){
if(parseInt(map[i][j]) == 0){
$("#container").append("<div class='air'></div>");
}
if(parseInt(map[i][j]) == 1){
$("#container").append("<div class='block'></div>");
}
if(parseInt(map[i][j]) == 2){
$("#container").append("<div class='spike'></div>");
}
}
}
}
window.onload=function() {
DrawMap();
}
更多代码:
var guy=document.getElementById('guy');
var up = 0;
var guyLeft = 0;
var health = 100;
function anim(e){
if(e.keyCode==83){
up +=10;
guy.style.top = up + 'px';
if(up >=400){
up -=10;
}
}
if(e.keyCode==87){
up -=10;
guy.style.top = up + 'px';
if(up <=0){
up +=10;
}
}
if(e.keyCode==68){
guyLeft +=10;
guy.style.left = guyLeft + 'px';
if(guyLeft >= 700){
guyLeft -= 10;
}d
}
if(e.keyCode==65){
guyLeft -=10;
guy.style.left = guyLeft + 'px';
if(guyLeft <= 0){
guyLeft += 10;
}
}
}
document.onkeydown=anim;im;
解决方法:
简答:使用document.elementFromPoint(x,y);
来检测哪个元素位于播放器的位置.
答案很长:看看下面的代码片段.
现在,我意识到我在代码中改变了很多,包括对功能进行了不必要的更改.我道歉,这是因为最初我只是为自己玩,但现在它正在运作,它可能对某人有用.
(您可能不知道使用的某些语法,请参阅帖子的底部以获得一些解释.)
碰撞部分是函数checkCollision()和$(document).keydown中的if子句:
>在keydown if-clauses中调用checkCollision():else {tile = checkCollision(…);.
>基本上我会检查玩家的前方(topview)是否会在即将到来的位置发生碰撞:
(for(var i = corner1; i< corner2; i){...}).
>基于碰撞磁贴(‘spike’或’block’),我要么生成一个警报(console.log),要么将checkTile返回到调用checkCollision()的if子句.
>如果返回tile,则tile的位置用于确定玩家的位置:
$(player).css(“left”,(tile?$(tile).offset().left $(tile).width():x));.
代码段:
//DOCUMENT-READY==========================
$(document).ready(function() {
//VARS----------------------------------
var step = 10;
var health = 100;
//MAP-----------------------------------
var map = [
[0,1,0,0,0,1,0,0],
[0,1,0,0,0,1,0,0],
[0,1,0,0,0,1,0,0],
[0,1,1,1,0,1,0,0],
[0,0,0,0,0,0,0,2]
];
//DRAW MAP------------------------------
(function() {
var tile = "";
for (var y=0,county=map.length; y<county; ++y) {
$("#canvas").append('<div class="tile-row" id="row_'+(y+1)+'"></div>');
for (var x=0,countx=map[y].length; x<countx; ++x) {
switch (parseInt(map[y][x])) {
case 0: tile="air"; break;
case 1: tile="block"; break;
case 2: tile="spike"; break;
default: tile="error";
}
$("#row_"+(y+1)).append('<div class="tile '+tile+'"></div>');
}
}
})();
//SET BOUNDARIES------------------------
var xMin=$("#canvas").offset().left, xMax=xMin+$("#canvas").width()-$("#player").width();
var yMin=$("#canvas").offset().top, yMax=yMin+$("#canvas").height()-$("#player").height();
//PLACE PLAYER--------------------------
$("#player").css("left",xMin).css("top",yMin);
//MOVE PLAYER---------------------------
$(document).keydown(function(e){
var player=document.getElementById("player"), tile=null;
var x=$(player).offset().left, playerLeft=x, playerRight=playerLeft+$(player).width();
var y=$(player).offset().top, playerTop=y, playerBottom=playerTop+$(player).height();
function checkCollision(playerCorner1x, playerCorner1y, playerCorner2x, playerCorner2y) {
var collisionTiles=["block","spike"];
//check if the front of the player is colliding with the environment
var front = (playerCorner1x==playerCorner2x?playerCorner1x:playerCorner1y);
var corner1 = (front==playerCorner1x?playerCorner1y:playerCorner1x);
var corner2 = (front==playerCorner1x?playerCorner2y:playerCorner2x);
//check every pixel along the front for collision
for (var i=corner1; i<corner2; ++i) {
var checkTile = document.elementFromPoint((front==playerCorner1x?front:i), (front==playerCorner1y?front:i));
if (collisionTiles.indexOf(checkTile.className.split(" ")[1]) != -1) {
if ($(checkTile).hasClass("spike")) {console.log("YOU DEAD!");}
else if ($(checkTile).hasClass("block")) {return checkTile;}
break;
}
}
}
if(e.which==37 || e.which==65){ //LEFT,A
x -= step;
if (x <= xMin) {x = xMin;}
else {tile = checkCollision(playerLeft-step,playerTop, playerLeft-step,playerBottom);}
$(player).css("left",(tile?$(tile).offset().left+$(tile).width():x));
}
if(e.which==39 || e.which==68){ //RIGHT,D
x += step;
if (x >= xMax) {x = xMax;}
else {tile = checkCollision(playerRight+step,playerTop, playerRight+step,playerBottom);}
$(player).css("left",(tile?$(tile).offset().left-$(player).width():x));
}
if(e.which==38 || e.which==87){ //UP,W
y -= step;
if (y <= yMin) {y = yMin;}
else {tile = checkCollision(playerLeft,playerTop-step, playerRight,playerTop-step);}
$(player).css("top",(tile?$(tile).offset().top+$(tile).height():y));
}
if(e.which==40 || e.which==83){ //DOWN,S
y += step;
if (y >= yMax) {y = yMax;}
else {tile = checkCollision(playerLeft,playerBottom+step, playerRight,playerBottom+step);}
$(player).css("top",(tile?$(tile).offset().top-$(player).height():y));
}
});
});
div {margin:0; padding:0; border-style:none; Box-sizing:border-Box; overflow:hidden;}
/*CANVAS================*/
#canvas {display:inline-block;}
/*TILES=================*/
.tile-row {width:100%; height:40px;}
.tile {float:left; width:40px; height:100%;}
.tile.air {background-color:skyblue;}
.tile.block {background-color:sienna;}
.tile.spike {background-color:gray;}
.tile.error {background-color:red;}
/*PLAYER================*/
#player {position:absolute; width:15px; height:15px; background-color:black;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="canvas"></div>
<div id="player"></div>
jsfiddle:https://jsfiddle.net/Lqw9w06z/11/
说明/评论:
>(function(){…})();是IIFE (Immediately Invoked Function Expression),它是一个自动执行的功能.
> front == playerCorner1x?playerCorner1y:playerCorner1x被称为Conditional (ternary) Operator,它基本上是一个紧凑的if子句.
>瓷砖的大小在CSS中设置:
.tile-row {width:100%;身高:40px;}和.tile {宽度:40px;高度:100%;}.
这决定了整个画布/游戏板的大小.
>我更改了你的for循环,以便一行的所有tile都包含在一个包含div中.
边注:
出于某种原因,碰撞未在某个特定地点登记(见下文).
如果有人能向我解释为什么会在这个特定的地方发生这种情况,我会很高兴的!