Ive written a small game in JavaScript with the html5 canvas and am at the point of collision detection and getting rather confused.
I build my levels in tiled and then import the saved JSON file into the game.
In my level draw function i have a check to see if there are any layer properties and if the layer properties are collisions. If it does, that layer is returned and the loop carries on. When finished, the layer that was returned with collisions gets put through another loop so that the the tile values can be put into an array.
So in this array i have i have a series of arrays depending on how many rows of tiles there are in the layer, and these rows hold the data for that row for each tile.
What i would like to do is when the player x/y is in one of the tiles which doesn't equal 0, then collide.
How would i do this if all i have is the value that is in that tile space?
Here is a link to the live version of the game so you can see for yourself how the tiles are stored, i have put in some console.logs so you might want to use firebug or equivalent to look at that. To log in use
Username - guest
password - guest
TO clarify my question is: How do i create collisions between my player x/y and a tile value??
Thanks very much
UPDATE
Ok so i think im nearly there, my problem at the moment is how do i read the objects x and y out of the array and then check the collision, at the moment the collision detection on works with the last tile in the array (the bottom right of the screen), here is the code i implemented to go through the array:
this.check_coll = function(array,posX, posY){
var collided = false,
block_x,
block_y,
block_cx,
block_cy,
combined_hw = 32,
combined_hh = 32,
player_cx = posX+(32/2),
player_cy = posY+(32/2);
array.forEach(function(value,i){
//get obj x
block_x = value[1];
//get obj y
block_y = value[2];
block_cx = block_x+(32/2);
block_cy = block_y+(32/2);
collided = Math.abs(player_cx - block_cx)< combined_hw
&& Math.abs(player_cy - block_cy)< combined_hh;
});
return collided;
}
Any ideas guys??
Related
I am trying to build a battleship game and using functions.
I wish to create and randomise 1 & 0 in my array every time I run the function as seen in the array below
Since it is a battlefield game, is there any way to make the 1s be in a row /column of 4/3/2/1? , to mimic the different sizes of the battleships
let battelfield = [
[0,0,0,1,1,1,1,0,0,0],
[0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,1,0,0,0],
[0,0,0,0,0,0,1,0,0,0],
[1,0,0,0,0,0,1,1,1,1],
[1,0,0,0,0,0,0,0,0,0],
[1,0,0,1,0,0,0,0,0,0],
[1,0,0,1,0,0,0,0,0,0],
[1,0,0,0,0,0,0,0,0,0]
]`
For a battleship, the way I would do it would be (assuming your grid is already filled with 0s):
For each ship
randomly select a starting position
randomly select a direction (up, down, left, right)
add your ship (by changing however many 1s you need to, based on the size of the ship).
The checks you need to add would be:
At step 1, make sure there isn't a boat there already, in which case pick again.
At step 2, make sure you're not going to hit the side of your game board, or another ship, in which case try another direction. If all 4 directions have been tried and there isn't enough space for a ship, back to step 1.
I usually don't give full answers when OP doesn't really show they tried but I liked the challenge.
The idea is to:
Set your empty board.
Choose a random point in the board where the ship will start
Choose direction (H or V)
With the random point and direction, make sure there is room for the ship according to the limits of the board
Create a list of positions the ship will take
Test all positions to make sure they are free
Set the positions on the board as filled.
At any given time, if a check is not fulfilled I've put continue; this will stop the current iteration and back to the beginning of the while. That way, the code runs until it finds a spot, and return to leave the loop.
Also, I've made a 1d array instead of 2d because it felt easier for mathing it out and manipulations. Feel free to convert to 2D afterward, or not.
let battlefield = new Array(10*10).fill(0);
placeShip(3);
placeShip(4);
placeShip(4);
placeShip(5);
console.log(battlefield);
function placeShip(length){
while(true){
const start = Math.round(Math.random()*99);
if(battlefield[start]==='1') continue;
const orientation = Math.random() <=.5?'H':'V';
// Fill the positions where the ship will be placed.
const positions = new Array();
if(orientation === 'H'){
// First make sure we have room to place it
if(10-((start+1) % 10) < length)continue;
for(let p=start;p<start+length;p++){
// Set for each length the position the ship will take.
positions.push(p);
}
}else if(orientation === 'V'){
// Same as for H but we divide by 10 because we want rows instead of cells.
if(10-((start/10) % 10) < length)continue;
for(let p=start;p<start+length*10;p+=10){
// Set for each length the position the ship will take.
positions.push(p);
}
}
// Now let's check to make sure there is not a ship already in one of the positions
for(let i=0,L=positions.length;i<L;i++){
if(battlefield[positions[i]]!=="0")continue;
}
// Now let's put the ship in place
for(let i=0,L=positions.length;i<L;i++){
battlefield[positions[i]] = 1;
}
return;
}
}
I am trying to create a basic 2D road system on a grid. Currently I have a list of staight lines but they are not connected to each other.
The part I am stuck on is how I construct the data and store my data so I know which waypoint points to which ever waypoint (more than one way point can connect to any other way point).
So currently if you image i have this as my data:
var point = [];
point[0] = {'x':2,'y':6};
point[1] = {'x':2,'y':8};
point[2] = {'x':6,'y':9};
point[3] = {'x':7,'y':2};
Now suppose point 0 connects to points 2 and 3. And point 1 connects to point 3.
What would be the best way to store the information that these points are linked, also allowing me then to look up and obtain properties of the object relating to a connected waypoint (which would mainly be useful for pathfinding in the future).
For example I may need to find a waypoint at a given x or y position. Or i may want to obtain relevant waypoint data that are connected to for example point 1, such as their x and y position and what ever waypoints may connect to them too.
The road network can be represented by an adjacency list. Basically, each point will be given a list (which could be implemented by an array) containing the indices which can be reached from it. In your example, this can be expressed as follows.
var point = [];
point[0] = {'x':2,'y':6, 'neighbors':[2,3]};
point[1] = {'x':2,'y':8, 'neighbors':[3]};
point[2] = {'x':6,'y':9, 'neighbors':[0]};
point[3] = {'x':7,'y':2, 'neighbors':[0,1]};
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
I'm creating a single player web RPG in JavaScript.
It will not be too heavy of an events-based game, but I will be loading lots of objects to the screen.
I have two questions:
1st: I've used createJS to load my bitmaps, but noticed severe lag when I loaded several objects to the screen at once and animated them. I'm wondering if there is a better library than createJS to load objects.
2nd: I was planning on using PHP for user profiles, stats, etc... but found writing AJAX calls to the server required several steps...
first, send javascript variable to php using jquery .get()
then update database
then send newly updated variable back by using json_encode, and echoing out the variable.
Finally, store that updated variable back in a javascript variable
I'm wondering how something like this is handled in NodeJS. I read How to decide when to use Node.js? to figure out the usage of NodeJS, and this sentence in particular, "I believe Node.js is best suited for real-time applications: online games, collaboration tools, chat rooms, or anything where what one user does with the application needs to be seen by other users immediately, without a page refresh." spoke to me... but I'm still not sure if I'll need to use NodeJS instead of PHP.
Thank you
EDIT:
Hi, I think I'm doing the tiling and caching incorrectly...
In my Game.php, I call several function to create/draw the objects.
Game.php:
function init() {
canvas = document.getElementById("demoCanvas");
start();
}
function start() {
stage = new createjs.Stage("demoCanvas");
stage.mouseMoveOutside = true;
//Create Objects
createWorld();
createTiles();
createPlayers();
In my function tick() I have a centerViewTo which centers the player in the viewport relative to the background (mimicking a camera).
The issue with this is, I pass in a single bitmap bgBMP that I was drawing the player relative to. If I do tiling, I'm not sure how I can draw the player relative to the background image.
centerViewTo(stage.canvas, stage, segment, {x:0, y:0, width:bgBMP.image.width, height:bgBMP.image.height});
Moreover, http://www.createjs.com/Docs/EaselJS/classes/DisplayObject.html#method_cache says I should cache each object before adding it to the container? Anyway, I get why you add all objects to the stage and then cache the stage all at once.
So I've tried that here... but it's not rendering anything:
CreateObjects.js:
var world;
var bgBMP;
var tile;
var mapWidth = 10; //Map size is 1000... so 10x10 tiles
var mapHeight = 10;
//World will be a container to hold all objects
function createWorld() {
world = new createjs.Container();
bgBMP = new createjs.Bitmap("images/bg2.png");
world.cache(0, 0, mapWidth , mapHeight );
world.addChild(bgBMP);
stage.addChild(world);
}
function createTiles() {
for (var x = 0; x < mapWidth; x++){
for (var y = 0; y < mapHeight; y++){
var tile = new createjs.Bitmap('images/myTile.png');
tile.x = x * 32;
tile.y = y * 32;
world.cache(0, 0, mapWidth , mapHeight );
world.addChild(tile);
}
}
}
I'm currently creating a RPG too with createjs, and I can display 200 characters, with their own animations and life, without lag issues.
Createjs is a really good framework, but you have to understand how it works to avoid performance issues. It's very important to separe layers in differents containers, and to cache them. For example, if the background of your game is composed with a lot of 32x32 tiles (like in RPG maker), you should cache it since it's not supposed to change during the game.
For example :
var backgroundContainer = new createjs.Container();
// mapWidth and mapHeight is the number of X and Y tiles
for (var x = 0; x < mapWidth; x++){
for (var y = 0; y < mapHeight; y++){
var tile = new createjs.Bitmap('mytile-'+i+'.png');
tile.x = x * 32;
tile.y = y * 32;
backgroundContainer.addChild(tile);
}
}
backgroundContainer.cache(0, 0, mapWidth, mapHeight);
stage.addChild(backgroundContainer);
When you cache a container, it will draw all the children in a hidden canvas, and then just draw the cached canvas on your current canvas on stage update.
If you don't cache it, just think that every time you call stage.update(), all your children will be drawn one per one on your canvas.
About NodeJS : nodeJS is really cool with the Socket.IO plugin, which use the full power of web sockets. Forget ajax if you need real time for a game : websocket is what you need. Try socket.io http://socket.io/ you will love it ;)
EDIT:
You don't use the cache well, I think you need to understand first what exactly does the cache. In my previous example, you can see we add all tiles in a container. So we have mapWidth * mapHeight tiles. Every time you call stage.update(), it will loop each tile bitmap and draw it on canvas. So if you have a 50x20 map, it will draw 1000 bitmaps every stage.update(), that's not good for performances.
If we cache backgroundContainer all tiles will be draw on an internal canvas, and when stage.update() is called it will only draw 1 image this time instead of 1000. You have to cache your world container after you add all the tiles, as in my example.
The power of createjs is that you can encapsulate your display objects as you want, this is how I organize my containers in my game :
stage
screen
scene
background -> Here I display a background image (E.g: the sky)
body
tiles -> All my background tiles (I cache this)
events -> Map events (moving NPC, my character, etc.)
overlay -> Here I display an overlay image (E.g: a fog image with 0.2 opacity)
transition -> Here I make transition when my character go to a new map
When my character move on the map, I just need to move the body container (changing X and Y properties)
I've created this rather simple javascript; balls or 'molecules' moving around the screen. I was hoping to add to the functionality that when one ball comes into contact with another, they swap velocities. We don't need to worry about any angles, just when they come into contact with each other, the velocities swap. (Instead of changing the velocities though, in the code linked I've just coded a colour change)
I've been trying to call the function 'someplace' to recognise when the molecules touch, but I've had no luck with that. I don't really understand why.
Link to code:
http://jsbin.com/arokuz/5/
There seems to be three main problems:
The molecules seem to be randomly changing, rather than when two molecules touch.
When one sets the array to have say, 3 molecules, only two appear, the first is actually there, but unresponsive to .fillstyle changes, so invisible against the canvas
With the function method I would only be able to recognise when molecules in series (1 and 2 or 4 and 5) in the array touch...how could I check all the molecules?
You are only comparing a molecule with 2 other ones, which in fact might be anywhere.
Collision detection is a topic quite hard to solve, but if you want to have your idea
working quickly you might go for a n^2 algorithm with 2 nested for loops.
the code is quite expected :
// collision
for(var t = 0; t < molecules.length-1; t++)
for(var tt = t+1; tt < molecules.length; tt++) {
var p1 = molecules[t];
var p2 = molecules[tt];
if (sq(p1.x-p2.x) +sq(p1.y-p2.y) < sq(p1.radius+p2.radius) )
{
p1.collided = 8; // will diplay for next 8 frames
p2.collided = 8; // .
}
}
the fiddle is here :
http://jsbin.com/arokuz/10
The reason only two appear when three are made isn't because the first one doesn't render it is rather the last one doesn't, this is because of how you draw them by comparing its distance with the next one in the list - as it is the last there is no next and thus throws a null error and continues (check the console).
The reason why they seem to "randomly" detect collisions or not is because they are not checking against all other molecules - only the next in the list, unfortunately the only simply way to do it would be to go through all other balls for every ball and checking.
To get the molecules to detect distance you could use the pythagorean theorem, I typically use it such as:
var distx = Math.abs(molecule1.x - molecule2.x);
var disty = Math.abs(molecule1.x - molecule2.y);
var mindist = molecule1.radius + molecule2.radius;
return Math.sqrt(distx*distx+disty*disty) < mindist;
UPDATE: I found this enormously helpful article explaining canvas per-pixel collision detection.
I'm working on a collision system for a javascript game using HTML5 canvas. Each object has an image as a sprite and when a non-transparent pixel of any one object overlaps another, the collision code is triggered. But before anything else the objects need to be moved so that they are just touching each other and no longer triggering a collision. I need help calculating the overlap of any two objects in terms of x and y in order to move one accordingly. Here's what we know:
The coordinates of the collision point relative to each object
The positions of the objects (and therefore the distance between them)
The width and height of the objects
The velocity of the objects in the x and y directions (a vector)
Another note: the images for these objects are uneven shapes, no perfect circles, but the radius from the center to the collision point can be calculated.
EDIT: I haven't seen a lot of response, so I'll be more specific. In the image below, two objects are colliding. The overlap area is in red. How would you go about finding the lengths of the green lines?
I'm honestly clueless about HTML 5 and how you can make games in pure HTML 5. But you would also need to know a velocity (IE, their direction. This way you can send them backwards from where they came)
If it was in a standard programming language, one method would be to use a while loop (moving the sprite back until the collision == false). Another method would be a more complicated calculation of how far the intersection is and subtract individual x and y values so they are not collided.
EDIT:
Then the easiest way is like I said, to put the object thats moving in a while loop that moves it backwards 1 pixel in each axis until its collision tests false. Example:
int x1 = 500; //x location on screen
int y2 = 500; //y location
public boolean fixOffSetX(Sprite s) {
int x2 = s.getX();
int y2 = s.getY();
//not writing the whole thing
//enter a while loop until its not colliding anymore
while(collision is still true) {
x--; or x++;
//depending on direction
//(which is why you need to know velocity/direction of your sprites)
//do the same for the Y axis.
}
}
//This method will return if the 2 sprites collided, you do this one
public boolean collisionTest(Sprite s1, Sprite s2) {}
You should look at doing very basic collisions, since it is a VERY complicated part of programming
If this is still an issue, I've found information about the subject in an e-book called Foundation Game Design with HTML5 en Javascript. Here: link to relevant pages. Hope this helps anyone in the future.