This is what I am doing right now:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>untitled</title>
<meta name="generator" content="TextMate http://macromates.com/">
<style type="text/css" media="screen">
body { font-family:"HelveticaNeue-Light"; margin: 0px; }
input { width: 75%; }
#wrap { background: #f1f1f1; border: 1px solid #d9d9d9; padding: 0px; }
/* #sprite { position: relative; background: #909090; width: 20px; height: 20px; padding: 20px; }*/
#spriteChatBubble { position: relative; background: #fff; border: 1px solid #000; font-size: 10px; max-width: 200px; }
#controlArea { margin-top: 50px; }
.button { background: #fff; color: #0080ff; padding: 5px; border: 1px solid #0050ff; text-decoration: none; }
.button:active { background: #0080ff; color: #fff; }
</style>
<script type="text/javascript" charset="utf-8">
$(document).ready(function() {
// on load
updatePos();
// get it ready
$("#sprite").css("background-image", "url(left100by100.png)");
// our main block
function detectCollision() {
var spritePos = $("#sprite").position();
var spritePosLeft = spritePos.left;
var spritePosTop = spritePos.top;
var chunkPos = $("#chunk").position();
var chunkPosLeft = chunkPos.left;
var chunkPosTop = chunkPos.top;
// show the chunk's position values (test)
$("#posLeftChunk").text(posLeftChunk);
if (spritePosLeft == chunkPosLeft || spritePosTop == chunkPosTop) {
// make it go somewhere random! :D
var randomLeft = Math.floor(Math.random() * 100);
var randomTop = Math.floor(Math.random() * -100);
// $("#chunk").hide();
$("#chunk").css("top", randomTop + "px");
$("#chunk").css("left", randomLeft + "px");
// $("#spriteChatBubble").animate({"top": "-=" + randomTop}, "fast");
}
}
setInterval(detectCollision, 500);
function insertValues(name){
var name = "foop";
var spritePosition = $("#sprite").position();
var leftVal = spritePosition.left;
var topVal = spritePosition.top;
}
insertValues("");
function showMessage(message) {
$("#spriteChatBubble").show('slow');
$("#messageText").text(message);
$("#spriteChatBubble").delay(5000).hide('slow');
}
function updatePos() {
var position = $("#sprite").position();
$("#posLeft").text(position.left);
$("#posTop").text(position.top);
// updatePos();
// insert the values into a database
insertValues("");
}
$(document).keydown(function(ee) {
$("#spriteChatBubble").hide(); // no need to show this!
// if ($("#sprite").position.left < 0) {
// alert();
// } // fail
if (ee.keyCode == 37) {
// going left!
$("#sprite").css("background-image", "url(left100by100.png)");
// alert("going left!");
$("#sprite").animate({"left": "-=50px"}, "fast");
$("#spriteChatBubble").animate({"left": "-=50px"}, "fast");
updatePos();
}
if(ee.keyCode == 39) {
// going right!
$("#sprite").css("background-image", "url(right100by100.png)");
// alert("going right!");
$("#sprite").animate({"left": "+=50px"}, "fast");
$("#spriteChatBubble").animate({"left": "+=50px"}, "fast");
updatePos();
}
if(ee.keyCode == 38) {
$("#sprite").animate({"top": "-=50px"}, "fast");
$("#spriteChatBubble").animate({"top": "-=50px"}, "fast");
updatePos();
}
if(ee.keyCode == 40) {
$("#sprite").animate({"top": "+=50px"}, "fast");
$("#spriteChatBubble").animate({"top": "+=50px"}, "fast");
updatePos();
}
});
$("#left").click(function() {
$("#sprite").animate({"left": "-=50px"}, "fast");
updatePos();
});
$("#right").click(function() {
$("#sprite").animate({"left": "+=50px"}, "fast");
updatePos();
});
$("#talkButton").click(function() {
showMessage($("#speakField").val());
$("#speakField").val("") ;
});
});
</script>
<!-- Date: 2011-05-23 -->
</head>
<body>
<!-- <div id="spriteChatBubble">
<a class="mt" id="messageText">message</a>
</div> -->
<!-- avatar (you, the player) -->
<div id="sprite" style="position: relative; background: url('right100by100.png'); width: 100px; height: 100px;">
</div>
<!-- chunks -->
<div id="chunk" style="position: relative; background: #909090; width: 20px; height: 5px; top: 100px; left: 80px;"></div>
<div id="controlArea">
position.left: <a id="posLeft">0</a><br>
position.top: <a id="posTop">0</a><br>
<br><br>
position.left (chunk): <a id="posLeftChunk">0</a><br>
position.top (chunk): <a id="posTopChunk">0</a><br>
<!-- <input type="text" id="speakField" onchange="javascript:void(0);">
<a href="javascript:void(0);" class="button" id="talkButton">talk!</a>
<a href="javascript:void(0);" onclick="showMessage('foo');" class="button" id="">test it</a>
<br><br>
<a href="javascript:void(0);" class="button" id="left">(</a>
<a href="javascript:void(0);" class="button" id="right">)</a>
-->
</div>
开发者_如何学C
</body>
</html>
Which moves it by 50 pixels in the desired direction, however detecting div collision (the sprite hitting the "chunk") and then it needs to be relocated. Do you know a better way to detect the divs colliding? Thanks.
I'll give you a theoretical answer:
You want to calculate your div's bounds -- get your x,y corner values and see if any other div's boundaries intersect your other div's values. If there's an intersection of coordinates then you have yourself a collision.
How to get location coordinates:
Top: $("#div").offset().top
Left: $("#div").offset().left
Bottom: $("#div").offset().top + $("#div").height()
Right: $("#div").offset().left + $("#div").width()
function collision($div1, $div2) {
var x1 = $div1.offset().left;
var y1 = $div1.offset().top;
var x2 = $div2.offset().left;
var y2 = $div2.offset().top;
if ((y1 + $div1.outerHeight(true)) < y2 ||
y1 > (y2 + $div2.outerHeight(true)) ||
(x1 + $div1.outerWidth(true)) < x2 ||
x1 > (x2 + $div2.outerWidth(true)))
return false;
return true;
}
Try this?
Try jquery-collision. Full disclosure: I wrote this recently and just uploaded it. I ran into this myself recently, and didn't see an obvious solution, so I decided to make a plugin myself and post it on source-forge.
It allows you to do:
var hit_by_sprite = $("#sprite").collision("#chunk");
or "#chunk" can be some kind of ".obstacle" and it will return all class="obstacle" that overlap id="sprite".
I use this technique ... the function could be optimized, but I've left it a little verbose for clarity:
function hitTest(a, b){
var aPos = a.position();
var bPos = b.position();
var aLeft = aPos.left;
var aRight = aPos.left + a.width();
var aTop = aPos.top;
var aBottom = aPos.top + a.height();
var bLeft = bPos.left;
var bRight = bPos.left + b.width();
var bTop = bPos.top;
var bBottom = bPos.top + b.height();
// http://tekpool.wordpress.com/2006/10/11/rectangle-intersection-determine-if-two-given-rectangles-intersect-each-other-or-not/
return !( bLeft > aRight
|| bRight < aLeft
|| bTop > aBottom
|| bBottom < aTop
);
}
This works nicely enough - used it in a few small games. You can replace position()
with offset()
if you want to account for borders and padding.
I also recommend replacing this:
$("#sprite").animate({"left": "+=50px"}, "fast");
with something like:
// at top of script cache #sprite selector if possible
var sprite = $("#sprite");
var spriteX = 0;
//... when you do the key check:
spriteX += 10;
sprite.css("left", spriteX);
This will be a bit faster, no reason to use animate for linear interactive motion. No reason to constantly select #sprite
, you should the selector.
I might be reading something wrong, but some of the examples provided seem either wrong, or not informative enough. When checking for collision, you can't just check one side, because you're cutting out an entire plane. You also can't just check one div, because the one you're trying to place may engulf the placed div, and you might need to check that collision as well.
I've been attempting collision detection on images, but it can easily be converted for divs. I've included all the functions that relate to this. My goal was to be able to place a div anywhere I want on the page, and randomize images, as well as their placement, without affecting anything else on the page. Obviously, if you want to use this, you'll need to change image names to your on images, with your own paths.
Also, if you use this with a lot of images, or in a tight space, or just simply want a failsafe, a counter could be added to the while
loop, which would be used to break the loop if a certain number was ever reached. This would prevent the page from locking up if it was having issues finding places for everything.
Hopefully someone who ends up here like I did, can use it.
CSS
#imageHolder {
z-index: -1;
background-color:red;
height: 700px;
width: 200px;
position: absolute;
top: 3px;
}
.preloadedImage {
display: none;
}
.loadedImage {
display: normal;
position: absolute;
z-index: -1; /* Can be removed. Places the Images underneath everything on the page.
}
Function returns a random number
function Random_Number(maxNumber) {
rndNumber = Math.floor(Math.random() * maxNumber);
return rndNumber;
}
Function returns a random position
//Params provide size of the image and which element to use for measurements.
//Don't want a left position to be against the edge, otherwise it will
//flow passed the div. However, if you want to achieve this look, just pass in 0,0 or remove them.
function Random_Position(elem, imgHeight, imgWidth) {
var top = Math.floor(Math.random() * ($(elem).height() - imgHeight));
var left = Math.floor(Math.random() * ($(elem).width() - imgWidth));
var pos = [top, left];
return pos;
}
Main Function
function Randomize_Images(elem, numOfImgs, imgNameArr) {
var imgIDs = [];
var collision;
var rndImgPos; //needs to be declared outside of loops so it can access outside of loops.
for (var z = 0; z < numOfImgs; z++) {
imgIDs.push("rndImg" + $(elem).attr("id") + z);
}
//Main loop - each iterations places a random image inside the div free of collision
for (var i = 0; i < numOfImgs; i++) {
//Create the image and hide it until its position has been set.
$(elem).append($("<img />", {
src: "libs/images/random_images/" + imgNameArr[Random_Number(imgNameArr.length)] + ".png",
id: imgIDs[i],
class: "preloadedImage"
}));
collision = true;
//Collision loop. Will not exit unless its forced, or finds a free a spot.
while (collision) {
//the image that will be added.
var curImg = $("#" + imgIDs[i]);
rndImgPos = Random_Position(elem, curImg.height(), curImg.width());
var imgTop = rndImgPos[0];
var imgBot = rndImgPos[0] + curImg.height();
var imgLeft = rndImgPos[1];
var imgRight = rndImgPos[1] + curImg.width();
//no reason to check for collision with the first image.
if (i >= 1) {
//Image loop. Will loop through all images previously placed, and check for collision.
for (var x = 0; x < i; x++) {
var setImg = $("#" + imgIDs[x]);
var setImgPos = setImg.position();
var setTop = setImgPos.top;
var setBot = setImgPos.top + setImg.height();
var setLeft = setImgPos.left;
var setRight = setImgPos.left + setImg.width();
if (((imgLeft < setLeft && imgRight > setLeft) || (imgLeft < setRight && imgRight > setRight)) && ((imgTop < setTop && imgBot > setTop) || (imgTop < setBot && imgBot > setBot))) {
collision = true;
break;
}
else if (((setLeft < imgLeft && setRight > imgLeft) || (setLeft < imgRight && setRight > imgRight)) && ((setTop < imgTop && setBot > imgTop) || (setTop < imgBot && setBot > imgBot))) {
collision = true;
break;
}
else {
collision = false;
}
}
}
else {
collision = false;
}
}
//Set the coordinates for the new image, and assign it's permanent class.
var curImg = $("#" + imgIDs[i]);
$(curImg).css("top", rndImgPos[0]);
$(curImg).css("left", rndImgPos[1]);
curImg.removeClass("preloadedImage");
curImg.addClass("loadedImage");
}
}
Example to call it
//I am calling the function here after window load, with an additional 2 second pause because I have a Datatable loading, and it adds to the height of the page. For this particular call, I want the div to be the length of the entire page. You don't need anything but the function call otherwise.
$(window).on("load", function(){
setTimeout(function(){
var imgNames = ["bullethole1", "bullethole2", "bullethole3", "bullethole4", "bullethole5", "bullethole6"];
$("#imageHolder").height($(document).height());
Randomize_Images($("#imageHolder"), 20, imgNames);
},2000);
});
精彩评论