更新时间:2022-12-06 17:19:10
简短答案:使用
I'm trying to make a simple game using jquery,javascript,html and css. I keep getting stuck on collision detection.
code:
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();
}
more code:
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;
Short answer: use document.elementFromPoint(x,y);
to detect which element is at the position of the player.
Long answer: Have a look at the code snippet below.
Now, I realize that I changed a whole lot in your code, including unnecessary changes for functionality. My apologies, this is because initially I was just playing around for myself, but now that it's working, it might be useful for somebody.
(Some of the syntax used may be unknown to you, see the bottom of my post for some explanations.)
The collision part is in function checkCollision()
and the if-clauses inside $(document).keydown
:
checkCollision()
is invoked: else {tile = checkCollision(...);
.for (var i=corner1; i<corner2; ++i) {...}
).
console.log
), or I return the checkTile
to the if-clause that invoked checkCollision()
.tile
is returned, the tile
's position is used to determine the position of the player
:$(player).css("left",(tile?$(tile).offset().left+$(tile).width():x));
.Code snippet:
//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/
Explanations/Comments:
(function(){...})();
is a IIFE (Immediately Invoked Function Expression), it's a function that is automatically executed.front==playerCorner1x?playerCorner1y:playerCorner1x
is called a Conditional (ternary) Operator, it's basically a compact if-clause..tile-row {width:100%; height:40px;}
and .tile {width:40px; height:100%;}
.for-loop
so that all the tiles of one row are wrapped in a containing div
.SIDENOTE:
For some reason, collision isn't registered at one specific spot (see below).
If someone can explain to me why this is happening in this one specific spot, I'd be delighted!