Ok. I managed to make and use QuadTree for my collision Detection alghorithm and it works just fine. I have my enemies and put them in the QuadTree, than retrieve the candidates that could possibly collide with my hero. That is hitTestObject() many agains one.
The problem I reached is how to test fastly whether some of the enmies collide with my hero's bullets. Roughly I have 4-6 bullets on the stage at same time. In this case I have hitTstObject 4-6 bullets against many enemy objects, which in turns gives me for cycle in for cycle so even using quad tree after a while things start to lag on the stage :)
I used this tutorial quadtree in java to develop m alghorithm but it works fine only in the above case. What should I do in this circumstance? Use another algorithm for many agains many or ?
Roughly this is the code
bulletsQuadTree.clear();
for (var bIndex:uint; bIndex < allEnemies.length; bIndex += 1 )
{
bulletsQuadTree.insert(allEnemies[bIndex]);
}
for (var bc:uint = 0; bc < bullets.length; bc += 1 )
{
var enemiesCollideBullets:Array = new Array();
bulletsQuadTree.retrieve(enemiesCollideBullets, bullets[bc]);
for (var dc:uint = 0; dc < enemiesCollideBullets.length; dc += 1 )
{
if (enemiesCollideBullets[dc].hitTestObject(bullets[bc]))
{
enemiesCollideBullets[dc].destroy();
enemiesCollideBullets.splice(dc, 1);
}
}
}
So this happens on each frame which are many operations per frame :(
Each bullet is treated as a hero and an array of enemies is returned for each bullet that could possibly collide with.
If you want to improve the performance of this loop, change this line:
enemiesCollideBullets[dc].hitTestObject(bullets[bc]);
The actionscript hit test functions are slow. A much better approach for bullets is to check for the distance.
var distanceSquared:number = (bullet.width/2 + object.width/2) * (bullet.width/2 + object.width/2);
if((bullet.x - object.x)* (bullet.x - object.x) + (bullet.y - object.y)* (bullet.y - object.y) < distanceSquared) {
// its a hit!
Related
I am writing a program that outputs the shortest route between two points on a map. The problem is that if the route is too long and it has many points that define its path it slows the program a lot and I am looking for a way to draw just some points instead of all the points in the array.
My approach goes as follows: the map has a zoom, each time the zoom changes check which points overlaps with the others. All the points that doesn't overlap go into the routeToDraw list and then it is drawn.
To check if the points overlap or not I have the following function:
//route is a list of latitude and longitude points
LinkedList<Point.Double> route = MapPanel.this.getGlassPane().getRoute();
LinkedList<Point.Double> routeToDraw = new LinkedList<Point.Double>();
int ovalSize = 8;
boolean compareMorePoints;
for(int i = 0; i < route.size(); i++) {
Point p1 = getScreenCoordinates(route.get(i).x, route.get(i).y);
compareMorePoints = true;
int j = i + 1;
while (j < route.size() && compareMorePoints == true) {
Point p2 = getScreenCoordinates(route.get(j).x, route.get(j).y);
if (Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2)) > ovalSize ) {
routeToDraw.add(route.get(i));
compareMorePoints = false;
}
j++;
}
}
MapPanel.this.getGlassPane().setRouteToDraw(routeToDraw);
The problem is that this function is quite expensive and although it does reduce the amount of points to draw and I seem to obtain some speed after calculating routeToDraw I don't think it is worth the wait each time I zoom in or out.
The ideal solution would be something like Google Maps' does when routing, drawing a series of equidistant points that modify each time you zoom in or out and look quite nice.
Two suggestions...
(old trick)... Don't do unnecessary math inside of a loop. You can and should eliminate the sqrt function, which is an "expensive" math operation when doing distances. Just compare to the square of ovalSize. It is mathematically equivalent.
Is your list sorted in any way? If there were a convenient point in your program to sort your list (or a copy of it) before displaying, then you could very quickly:
Lop off the first and last part that is outside your zoom window in one of the coordinates (say X, if you sorted by X) by doing a binary search for the window boundary
Tighten up your loop to only look at neighbors within a window of concern, and do a sliding window instead of all-compared-to-all.
I am having a problem with a basic code which displays some animated images in a 150x150 grid on the screen. (Note: Yes i know the images go off the edge of the screen but in the end i was planning to scale the images as required to fit the screen). However the program only runs at 2 FPS causing the animation to sometimes not work. My loop is currently as follows (in Java):
for (int i = 0; i < 22; i++) {
for (int j = 0; j < 11; j++) {
g2d.drawImage(getImage(texture_Ocean,l),i*64,j*64,i*64+64,j*64+64,0,0,64,64,this);
}
}
And getImage:
public Image getImage(Image i, Long l) {
BufferedImage b = (BufferedImage) i;
int w = b.getWidth();
if (b.getHeight() % w == 0) {
int frames = b.getHeight()/w;
int frame = Math.round((l%1000)/(1000/frames));
System.out.println(frame);
return b.getSubimage(0,(int) (w*frame) ,w, w);
} else {
return texture_error;
}
}
My question is how can i make my program more efficient/run quicker? I know there has to be a way to do it as you see games such as prison architect and rimworld with words that are 300x300 and have hundreads of entities. And games such as TF2 which display thousands of polygons in 3D space. How?
The problem is that you are using the CPU (and through inefficient memory access methods as well) to do a job that the GPU is much better for.
You need to look at using something like a 2d graphics or games library or similar to get the sort of performance you are looking for.
The thing is, when developing games, you should care a lot with optimization. You can't simply call a paint method if you don't need it, and hope everything will be alright.
Besides that, you should try to look for a library dedicated to graphics (like OpenGL), since they can handle the optimization easily with the hardware.
I am trying to create rain animation in android/java using canvas.
The problem is the after raindrops go out of screen, they re-appear on air instead of appearing back in cloud.
What i want is,they should appear back in cloud and the distance between each row of raindrops should remain the same.
However after they go out of screen, the distance between each row changes and they stack on each other.
How can i fix that?
counter = 0;
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 10; j++) {
if(yrain[counter]<c.getHeight()){
yrain[counter] = 400+ yAdder[counter] +j*50;
yAdder[counter]+=rainSpeed;
}else{
yAdder[counter]=0;
yrain[counter] = 400+ yAdder[counter];
}
xrain[counter] = 300+ ((50) * i);
c.drawBitmap(rain[counter], xrain[counter], yrain[counter],null);
counter++;
}
}
Here is my suggestion - I have done it some years ago when needed to show some plot animation:
Double and repeat: suppose your rain starts at point Y10 and finish at Y0. Then you can generate a random matrix with drops that has to be updated in their positions moving down in relation to Y coordinate. It goes moving up to the distance (Y10-Y0)x2.
When this circle is completed, such as:
for(step=0;step<(full_cycle_steps);step++)
{ // update Y position downwards
perform_animation();
}
then you restart the animation that repeats itself.
Smooth motion: you need to apply relative DSP (digital sinal processing), so if you have Y10 to Y0, the interval is 10 integers, take this split by 100, i.e. 10x100 will give you 1000, as you are applying it with the idea of double and repeat, then you have: 10x100x2 = 2000, that means a vector with 2000 to be moving in your canvas/graph targeted coordinates, displayed in your plotting area (1000). Of course if you don't need to have the drop moving so smoothly you can make the number of your digital x analog matrix smaller.
Here you find some reference that can be insightful:
Matrix Rain
Simulating rain
jquery-matrix-digital-rain
Taking from here, you should be able to easily complete your rain animation.
This is more of a algorithmic question. I have a page which using javaScript displays items and items relationship to other item by drawing arrow connection from source to target (think jsPlumb). Each item can have 0 or more connections. The challenge i have is to place the divs/circles strategically with the container in the most optimum way .
optimum : Least number of connections (arrows connecting two circles) overlaps
Visual Example: Below picture is an unoptimised version of the display, having placed the circles randomly within the container .
Notice in above picture the number of connection (arrows) overlap is unnecessarily high. Below picture is one optimized solution with circles placed in better position resulting in no overlap of connection in this small example:
The size of container in which items are placed is 1020x800. where large number of circles exist there will always be overlaps so the idea is to minimize the amount of connection overlap. I am hoping for example of how this could be done as i find reading algorithm articles slightly daunting :(.
Approach 1
A pretty nice class of algorithms for laying out graphs are simulation-based algorithms. In those algorithms, you model your graph as if it was a physical object with physical properties.
In this case imagine the nodes of the graph are balls that repel each other, while the edges are springs or rubbers that keep the graph together. The repelling force is stronger the closer the nodes are to each other e.g. inverse square of their distance, and the tension force of each spring is proportional to its length. The repelling force will cause the nodes to get as far as possible from the other nodes and the graph will untie. Of course, you'll have to experiment with coefficients a little to get the best results (but I guarantee - it is a lot of fun).
The main pros of this approach are:
easy to code - nested loops calculating force between every node-node pair and updating node position
works for all kinds of graphs either planar or nonplanar
lots of fun to experiment
if you make it interactive, e.g. allow user to move nodes with a mouse - it attracts people and everyone wants to "play with the graph"
The downsides of this approach are:
it can get stuck in a local energy minimum (shaking or helping manually helps)
it is not extremely fast (but can make a nice animation)
A similar method can be used to layout/untie knots.
Sample code
<html>
<head>
</head>
<body>
<canvas id="canvas" width="800" height="600" style="border:1px solid black"/>
<script>
window.requestAnimFrame = (function(callback) {
return window.requestAnimationFrame || window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame ||
function(callback) {
window.setTimeout(callback, 1000 / 120);
};
})();
var width = 800;
var height = 600;
function addEdge(nodeA, nodeB) {
if (nodeA.edges.indexOf(nodeB) == -1) {
nodeA.edges[nodeA.edges.length] = nodeB;
nodeB.edges[nodeB.edges.length] = nodeA;
}
}
function createGraph(count) {
var graph = new Array();
for (var i = 0; i < count; i++) {
var node = new Object();
node.x = Math.floor((Math.random() * width));
node.y = Math.floor((Math.random() * height));
node.edges = new Array();
graph[i] = node;
if (i > 0)
addEdge(graph[i], graph[i - 1]);
}
for (var i = 0; i < count / 2; i++) {
var a = Math.floor((Math.random() * count));
var b = Math.floor((Math.random() * count));
addEdge(graph[a], graph[b]);
}
return graph;
}
function drawEdges(ctx, node) {
for (var i = 0; i < node.edges.length; i++) {
var otherNode = node.edges[i];
ctx.beginPath();
ctx.moveTo(node.x, node.y);
ctx.lineTo(otherNode.x, otherNode.y);
ctx.stroke();
}
}
function drawNode(ctx, node) {
ctx.beginPath();
ctx.arc(node.x, node.y, 30, 0, 2 * Math.PI, false);
ctx.fillStyle = 'green';
ctx.fill();
ctx.lineWidth = 5;
ctx.strokeStyle = '#003300';
ctx.stroke();
}
function drawGraph(ctx, graph) {
ctx.fillStyle = 'white';
ctx.fillRect(0, 0, width, height);
for (var i = 0; i < graph.length; i++)
drawEdges(ctx, graph[i]);
for (var i = 0; i < graph.length; i++)
drawNode(ctx, graph[i]);
}
function distanceSqr(dx, dy) {
return dx * dx + dy * dy;
}
function force(nodeA, nodeB, distanceFn) {
var dx = nodeA.x - nodeB.x;
var dy = nodeA.y - nodeB.y;
var angle = Math.atan2(dy, dx);
var ds = distanceFn(distanceSqr(dx, dy));
return { x: Math.cos(angle) * ds, y: Math.sin(angle) * ds };
}
function repelForce(distanceSqr) {
return 5000.0 / distanceSqr;
}
function attractForce(distanceSqr) {
return -distanceSqr / 20000.0;
}
function gravityForce(distanceSqr) {
return -Math.sqrt(distanceSqr) / 1000.0;
}
function calculateForces(graph) {
var forces = new Array();
for (var i = 0; i < graph.length; i++) {
forces[i] = { x: 0.0, y: 0.0 };
// repelling between nodes:
for (var j = 0; j < graph.length; j++) {
if (i == j)
continue;
var f = force(graph[i], graph[j], repelForce);
forces[i].x += f.x;
forces[i].y += f.y;
}
// attraction between connected nodes:
for (var j = 0; j < graph[i].edges.length; j++) {
var f = force(graph[i], graph[i].edges[j], attractForce);
forces[i].x += f.x;
forces[i].y += f.y;
}
// gravity:
var center = { x: 400, y: 300 };
var f = force(graph[i], center, gravityForce);
forces[i].x += f.x;
forces[i].y += f.y;
}
return forces;
}
function updateNodePositions(graph) {
var forces = calculateForces(graph);
for (var i = 0; i < graph.length; i++) {
graph[i].x += forces[i].x;
graph[i].y += forces[i].y;
}
}
function animate(graph) {
var ctx = document.getElementById("canvas").getContext("2d");
for (var i = 0; i < 20; i++)
updateNodePositions(graph);
drawGraph(ctx, graph);
requestAnimFrame(function() { animate(graph); });
}
animate(createGraph(8));
</script>
</body>
</html>
You can see how this code works here. Refresh the page to get different graphs.
Of course, sometimes it doesn't find the global minimum and there are more crossing edges than it is possible - so if the results don't satisfy you, you can add random shaking.
Approach 2
This problem is similar to routing problem in design of PCBs. If you're not satisfied with the simple and easy solution provided by Approach 1, you can improve the solution by using autorouting methods. E.g. you can put your nodes on a grid and then use A* algorithm to find the shortest paths connecting them.
Use Approach 1 to find a suboptimal initial solution (optional).
Remove all edges. Place the nodes on a grid (round up their coordinates). The grid must have enough resolution so that no two nodes overlap.
Sort the edges in ascending approximated length (use Euclidean or Manhattan metric).
For each edge use A* algorithm to find the shortest route to connect the nodes. As a cost function use not only the distance from the source node, but also add enough large penalty for stepping onto any grid points that are already taken by any edge routed previously.
Mark the grid points on the path found in the previous step as "taken", so all next edges will favour paths not stepping on / intersecting with this path.
The above algorithm is a greedy heuristic and unfortunately it doesn't guarantee the optimal solution, because the result depends on the order of routing the edges. You can further improve the solution by removng a random edge that crosses another edge and reroute it.
Step 1. is optional to make the graph layout more regular and make the average connection distance small, however it should not affect the number of intersections (if the grid has enough resolution).
It looks like simple closed polygon extraction to me. try this:
forget about direction of connections
remove all redundant connections (bidirectional ones are duplicate)
find all closed loops
start point is always container with more than 2 connections (or just with 1) so loop through unused neighboring containers until get back to the start point (set this path as used) or until reach endpoint (1 connection only, also set this path as used) or until reach crossroad (connections > 2, also set this path as used).
repeat until there are no unused line between containers left.
after this you have your graph decomposed to non intersecting parts.
now join them back together so no connection is intersecting. Shared connections are inside and non shared connections are on the outside. Open loop (with endpoints) can be anywhere.
I hope this helps
I think the simulation-based algorithm would be the bbest choice, however, since your goal is to minimize overlapping arcs and not to optimize the distribution of nodes you should apply a repelling force between arcs (not between nodes) and use the nodes as springs.
Iteration:
For each arc in the graph compute its central point (averaging the starting point with the ending point)
for each couple of arcs apply a repulsion between their centres (both extremes of the arc move accordingly)
for each node in the graph compute its new position as the average of the connected arcs and update the related endpoint of the arc
You can also add a contraction phase with the nodes attracted to the middle of the graph (average of the coordinates of all the nodes).
Stop iterating when some stability threshold is reached.
I'm working in J2ME, I have my gameloop doing the following:
public void run() {
Graphics g = this.getGraphics();
while (running) {
long diff = System.currentTimeMillis() - lastLoop;
lastLoop = System.currentTimeMillis();
input();
this.level.doLogic();
render(g, diff);
try {
Thread.sleep(10);
} catch (InterruptedException e) {
stop(e);
}
}
}
So it's just a basic gameloop, the doLogic() function calls for all the logic functions of the characters in the scene and render(g, diff) calls the animateChar function of every character on scene, following this, the animChar function in the Character class sets up everything in the screen as this:
protected void animChar(long diff) {
this.checkGravity();
this.move((int) ((diff * this.dx) / 1000), (int) ((diff * this.dy) / 1000));
if (this.acumFrame > this.framerate) {
this.nextFrame();
this.acumFrame = 0;
} else {
this.acumFrame += diff;
}
}
This ensures me that everything must to move according to the time that the machine takes to go from cycle to cycle (remember it's a phone, not a gaming rig). I'm sure it's not the most efficient way to achieve this behavior so I'm totally open for criticism of my programming skills in the comments, but here my problem: When I make I character jump, what I do is that I put his dy to a negative value, say -200 and I set the boolean jumping to true, that makes the character go up, and then I have this function called checkGravity() that ensure that everything that goes up has to go down, checkGravity also checks for the character being over platforms so I will strip it down a little for the sake of your time:
public void checkGravity() {
if (this.jumping) {
this.jumpSpeed += 10;
if (this.jumpSpeed > 0) {
this.jumping = false;
this.falling = true;
}
this.dy = this.jumpSpeed;
}
if (this.falling) {
this.jumpSpeed += 10;
if (this.jumpSpeed > 200) this.jumpSpeed = 200;
this.dy = this.jumpSpeed;
if (this.collidesWithPlatform()) {
this.falling = false;
this.standing = true;
this.jumping = false;
this.jumpSpeed = 0;
this.dy = this.jumpSpeed;
}
}
}
So, the problem is, that this function updates the dy regardless of the diff, making the characters fly like Superman in slow machines, and I have no idea how to implement the diff factor so that when a character is jumping, his speed decrement in a proportional way to the game speed. Can anyone help me fix this issue? Or give me pointers on how to make a 2D Jump in J2ME the right way.
Shouldn't you be adjusting the jumpSpeed based on the elapsed time? That is, perhaps the speed changes by -75/sec, so your diff should be a weight for the amount of change applied to the jumpSpeed.
So pass in diff to checkGrav and do something like... jumpSpeed += (diff * (rate_per_second)) / 1000;
(assuming diff in milliseconds)
(Ideally, this would make it just like real gravity :D)
Why not just scale all constants by diff?
By the way, I'm embarrassed to say this, but I worked on a commercial game where gravity was twice as strong on characters going down as going up. For some reason, people preferred this.
This seems to be more of a question about game design than the math of a jump. It is a common problem that in games running on different processors one game will be executed faster and on other games it will be executed slower (thus changing the entire speed of the game). I'm not sure what common practice is in games, but whenever I made home-brewed 2D games (they were fun to make) I would have the concept of a game-tick. On faster machines
long diff = System.currentTimeMillis() - lastLoop;
lastLoop = System.currentTimeMillis();
Would be lower. A wait time would be derived from the diff so that the game would run at the same speed on most machines. I would also have the render method in a separate thread so that the game speed isn't dependent on the graphics.
I can give a formula like this (I use it everywhere). The X is the parameter of it starting from zero and ending on the length of jump.
if you want someone to jump at some Height (H) and at some Length (L), then function of the jump will look like this (and it won't' be able to ever look different):
y = minus(power(x - Length of Jump divided by two) multiply by 4 and
multiply by Height of the jump) divide by power of Length and add
Height of jump in the very end.
y = -(x-l/2)(x-l/2)*4*h/(l*l) + h
And if you want the jumping object to land on something, then you can check every new X if it's approximately standing on a platform and if it is standing on something, then don't make it just stop, make it's Y position exactly equal to the Y of platform.
If you're using something like Flash or other base which has inverted y axis, then multiply the function output by -1;