Collision/overlapping in a for loop in javascript - javascript

I'm writing a space invaders game on Khan Academy for a school project and I can't figure out how to put in a collision between bullets and the aliens and then get rid of the alien that the bullet collided with. It's very basic JS and as much as I've tried, I don't really understand how to put the other answers on this topic into my code. If anyone could help me on this I would be so grateful.
Here's a link to the game: http://www.khanacademy.org/cs/space-invaders/1087897437
I have another game with the same problem here: http://www.khanacademy.org/cs/brick/1176464164

In both cases, the game needs to run in a while loop. Basically, each iteration moves the game forward one 'frame'. One of the things to be calculated from one frame to the next, is whether or not a bullet has touched an alien.
Both a bullet and an alien have occupy a physical space. So you could effectively loop through all of the bullets and have a function that checks if a bullet has hit an alien.
function has_hit_alien(bullet) {
for(var i = aliens.size; i > 0; i--){
if(same_space(bullet, aliens[i]) {
return aliens[i]
}
}
}
Now you need to implement the same_space function to check if any of the outer pixels of argument 1 are inside of argument 2.

Related

I am trying to remove items from an array of objects used as projectiles for players or enemies to shoot in games made with JavaScript

I am practicing with making players and enemies for 2d games using vanilla JavaScript and HTML Canvas. The only problem I have is that I am trying to remove the projectiles from the playerProjectiles array when the projectile goes off of the screen. This is so that the game doesn't have to keep track of a bunch of projectiles that are not even on the screen, so the game will run smoother. I have tried sifting through the array using .forEach and splicing the current projectile that it is looping through as long as that projectile is off the screen. However, using this method, if there are multiple projectiles on the screen and one of them goes off of the screen, the entire array gets spliced and all of the projectiles are removed. What am I doing wrong here? Also, would it be better to put the code for the different mechanics of the projectiles in a different function? Etc. moving the projectiles up when they are shot out, actually drawing them to the screen, splicing them from the array when they go off the screen.
function populatePlayerProjectilesArray() {
playerProjectiles.forEach(projectile => {
projectile.draw();
projectile.y -= pdy;
if(projectile.y <= 0 - projectile.rad) {
playerProjectiles.splice(projectile)
}
})
}
Array.prototype.splice()
Examples:
splice(start)
splice(start, deleteCount)
deleteCount Optional An integer indicating the number of elements in the array to remove from start. If deleteCount is omitted [...], then all the elements from start to the end of the array will be deleted.
I think you want to change your splice statement to:
playerProjectiles.splice(projectile, 1)

How do I make my animation go slower?

I'm making a game with HTML5. With javascript, I'm making my character move when the user presses the arrow keys. The animation is made up of 6 sprites.
The thing is when I hold down the right arrow key (for example), my character moves smoothly but seems to be moving too fast. It's like a little bird flapping his wings so rapidly that you can barely see the appearance of the character.
Code snippet:
if (38 in keysDown) { // Player holding up
if (character.y>=0)
{
character.y -= character.speed * modifier;
position++;
if(position > NUM_POSITION)
position = 0;
}
}
My code implements the requestAnimationFrame and modifier (to manipulate the speed of the character per second).
I wonder how other people deal with a character that seems to be walking so fast. I'm not saying that the character TRAVELS across the page fast because I can just reduce the speed. I'm saying the character switches sprites so rapidly that you can barely see him unless you stop moving.
I found this example jsfiddle. In that case if you increase the x variable, the animation become faster.
I hope I could be a good example for your problem.
var elem=document.getElementById("toChange"); var x=0;
function moreVisible() {
if(x==1)clearInterval(t);
x+=0.05;
elem.style.opacity=x;
elem.style.filter="alpha(opacity="+(x*100)+")"; }
var t=setInterval(moreVisible,25);

How to check if an object is hitting another object during animation.

Hello and thanks for your time and help. I am building a mini golf game using HTML 5 Canvas. I have a golf ball that is able to be hit around with a specific power and direction and stoping and slowing down accordingly.
However, i am stuck on finding a optimal way of detecting wether the ball is hitting or over an obstacle on the course. I have each of the obstacle objects stored in an array. So it is easy to access the x,y,height, and width of the object. I was thinking it would be best to have a for loop that goes through each of the objects checking if the ball is hitting any of them during animation. Also the x and y of the golf ball is easily accessible, its values are stored in a dictionary.
Any suggestions of testing to see if any of the obstacles are being hit?
Here is the code on how i am testing for the boundaries and having the ball bounce back correctly
function animateGolfBall(timestamp){
if(powerBar.widthChange != 0){
context.clearRect(0, 0, canvasTag.width, canvasTag.height);
if (golfBall.x > canvasTag.width - 5 || golfBall.x < 5 ) {
golfBall.angle = 180 - golfBall.angle;
updateGolfBall();
drawEverything();
}
else if (golfBall.y > canvasTag.height - 5 || golfBall.y < 5) {
golfBall.angle = 360 - golfBall.angle;
updateGolfBall();
drawEverything();
}
else{
updateGolfBall();
drawEverything();
}
window.requestAnimationFrame(animateGolfBall);
powerBar.widthChange -= 1;
}
else{
golfBall.isMoving = false;
drawEverything();
}
}
Here is the code where the obstacles are being redrawn, and where i believe the check should be placed to see if the golf ball is hitting them
function drawObstacle(){
for(var i = 0; i < obsticles.length; i++){
obsticles[i].createSquare(obsticles[i].squareX/canvasTag.width,
obsticles[i].squareY/canvasTag.height,
obsticles[i].squareWidth/canvasTag.width,
0,
obsticles[i].squareHeight/canvasTag.height,
0,"pink",3,"yellow");
// if { need help with logic here
//And what to put here, and how ever many logical statements will be needed
// }
}
Any help or tips would be much appreciated. If you need more code or i wasn't clear on something please let me know and ill update my question.
This is called collision detection. There are many ways to deal with collisions. Depending on the shape of your objects (are they circles or squares or car-shaped) and what you want to happen when a collision occurs. Does the ball bounce back? Does it stop? Is it of the most importance that the collision is detected at the edge of the object?
You can read about simple collision detection working with either square or circle shaped objects here.

Detecting irregular Shape

Leading up from this question Detecting mouse coordinates with precision, I have learnt quite a bit in the past few days. Here are what I picked as best learning resources on this topic:
http://gamedev.tutsplus.com/tutorials/implementation/quick-tip-use-quadtrees-to-detect-likely-collisions-in-2d-space/
http://www.gamedev.net/page/resources/_/technical/graphics-programming-and-theory/quadtrees-r1303
http://jsfiddle.net/2dchA/2/
The code in (3) works in JSFiddle but breaks at this section in my testing environment (VS2012):
var myTree = new Quadtree({
x: 0,
y: 0,
width: 400,
height: 300
});
with the message Quadtree is undefined in IE. FF & Chrome just gloss over it and display an empty page. I couldn't sort it out. Question 1: Can someone help out with that?
My main question:
I have a region (parcels of land like a map) with about 1500 parcels drawn in html5, not jpg or png images. It is a lot of lines of code to complete that but the rendering is great, so I am keeping it that way. I intend to have a mouseover event tell me which parcel I am standing on when the mouse stops. As you will see in the previous question referred my previous attempts were not impressive. Based on the learning I have been doing, and thanks to Ken J's answer/comments, I would like to go with this new approach of slicing up my canvas into say 15 quads of 100 objects each. However, I would like some guidance before I take another wild dive the wrong way.
Question 2: Should I slice it up at creation or should the slicing happen when the mouse is over a region, ie, trail the mouse? The latter sounds better to me but I think I can do with some advice and, if possible, some start out code. The quadtree concept is completely new to me. Thanks.
Can't help with question 1.
You should definitely build the tree as early as possible, given that the objective is to get the page to respond as quick as possible once the user clicks somewhere.
Keep the tree for as long as the user interacts with the 2d area. Updating a quad tree shouldn't be too hard, so even if the area changes contents, you should be able to reuse the existing tree (just update it).
Given the fact that your draw area is well know i see no advantage in a QuadTree over a spacial hash function. This function will give you an integer out of an (x,y) point.
var blocWidth = 20;
var blocHeight = 20;
var blocsPerLine = ( 0 | ( worldWidth / blocWidth) ) + 1 ;
function hashPoint(x,y) {
return ( 0 | (x/blocWidth)) + blocsPerLine*(0|(y/blocHeight));
}
once you built that, hash all your parcels within an array :
parcelHash = [];
function addHash(i,p) {
if (!parcelHash[i]) { parcelHash[i]=[ p ]; return; }
if (parcelHash[i].indexOf(p) != -1 ) return;
parcelHash[i].push(p);
}
function hashParcel (p) {
var thisHash = hashPoint(p.x,p.y); // upper left
addHash( thisHash, p);
thisHash = hashPoint(p.x+width, p.y); // upper right
addHash(thisHash, p);
thisHash = hashPoint(p.x, p.y+p.height); // lower left
addHash(thisHash, p);
thisHash = hashPoint(p.x+width, p.y+p.height); // lower right
addHash(thisHash, p);
};
for (var i=0; i<allParcels.length; i++) { hashParcel(allParcels[i]) };
now if you have a mouse position, you can retrieve all the parcels in the
same block with :
function getParcels(x,y) {
var thisHash = hashPoint(x,y);
return parcelHash[thisHash];
}
I'll just give you few tips in addition to what others have said.
... have a mouseover event tell me which parcel I am standing on ...
From your other messages I conclude that parcels will have irregular shapes. Quadtrees in general work with rectangles, so you'd have to calculate the bounding rectangle around the shape of the parcel and insert that rectangle in the quadtree. Then are when you want to determine whether mouse is over a parcel, you'll query the quadtree which will give you a set of parcels that might be under the mouse, but you'll have to then do a more precise check on your own to see if it indeed is.
... when the mouse stops.
From your other questions I saw that you try to detect when the mouse has "stopped". Maybe you should look at it this way: mouse cursor is never moving, it's teleporting around the screen from previous point to next. It's always stopped, never moving. This might seem a bit philosophical, but it'll keep your code simpler. You should definitely be able to achieve what you intended without any setTimeout checks.
... slicing up my canvas into say 15 quads of 100 objects each.
... Should I slice it up at creation or should the slicing happen when the mouse is over a region
You won't (and can't) do slicing, quadtree implementation does that automatically (that's its purpose) when you insert or remove items from it (note that moving the item is actually removing then re-inserting it).
I didn't look into the implementation of quadtree that you're using, but here are two MX-CIF quadtree implementations in case that one doesn't work out for you:
https://github.com/pdehn/jsQuad
https://github.com/bjornharrtell/jsts/tree/master/src/jsts/index/quadtree
The problem in question 1 probably happens because jsfiddle (http) page is trying access quadtree.js which is on https

Detect loops in computer player in a cardgame

A while ago I created a small cardgame web app for fun. The player plays against the computer and mostly it works fine. Sometimes though the computer player gets into a loop, the point of the game is to lose all your cards and if you don't have a card to play you take the pile. Sometimes the computer plays x,y,z, takes the pile, plays x,yz, takes the pile etc.
I keep track of the moves I've made, so at any point I have an array that looks something like : [C2,D5,H2,S4,C5,H2,S4,C5,H2,S4,C5]
In this case I can see that I've gotten into a loop of playing H2,S4,C5, then taking the pile and then repeating.
So, the generalized problem is, what's the best way to detect repeating patterns in a list? I could probably whip something up using a simple for loop, trying to find the card I'm about to play and if I find that in position x then I could check whether the pattern from x to n repeats at position x-(n-x) to x, but this seems like the kind of problem that could have a nice algorithm for it. How would you code this given the following function signature:
function findLoops(previousMoves, nextMove, maxPatternLength) {
//Return [loopLength, loopCount] or null if there are no loops
}
p.s. this is not a homework assignment, the game exists and is at http://www.idiot-cardgame.com if anyone is interested :)
First the general question: Your suggested method
trying to find the card I'm about to play and if I find that in position x then I could check whether the pattern from x to n repeats at position x-(n-x) to x,
looks really good. I would suggest basically the same. It is O(n) and needs a fixed amount of storage, and is simple: what else would you wish for?
Second: You can check for repetition in games generally if you keep a hash table of all previous game states (complete state, nothing left out). Everytime you reach a new state look up if it is in the hashtable, if its in it: you game state is looping.
In Javascript you have builtin hastables so this is very easy to do with something similar like this:
new_state = next_move(old_state);
new_encoded_state = encode(new_state); // make it into a string
if (allstates[new_encoded_state]) {
// we are looping!
} else {
allstates[new_encoded_state] = 1;
// no looping
}
The variable allstates is not an Array but of type Object. You can have array like access with strings and this uses the Object as hastable.

Categories

Resources