I need to change the "bounce" method in the BallDemo class to allow a user to choose how many bouncing balls there are through a parameter. I need to use a collection to store the balls, and the balls should be placed in a row along the top of the default canvas. Also, the balls should erase when the last ball reaches the end of the canvas. I know I need to use an array list and a for loop for the draw, move, and erase methods but other than that I'm stuck. This is what I have so far:
/**
* Simulates a chosen number of specific balls bouncing.
*/
public void bounce(int amount)
{
int ground = 400; // position of the ground line
myCanvas.setVisible(true);
// draw the ground
myCanvas.drawLine(50, ground, 550, ground);
***ArrayList<BouncingBall> balls = new ArrayList<BouncingBall>();
for(int index; index < amount; index++)
{
BouncingBall ball = new BouncingBall(0, 0,***
// make them bounce
boolean finished = false;
while(!finished)
{
myCanvas.wait(50); // small delay
ball.move();
ball2.move();
// stop once ball has travelled a certain distance on x axis
if(ball.getXPosition() >= 550 && ball2.getXPosition() >= 550)
finished = true;
}
ball.erase();
ball2.erase();
}
}
The program right now is set to make two balls bounce because it didn't have a parameter at first, it was programmed to make two bouncing balls. The lines with the ArrayList and for loop are what I added but I'm stuck on there. Also, the default canvas has a width of 600 and a height of 500.
Related
So I have this body that is a circle collider
and it has sometimes a big velocity
the problem is that the tiled map of the boundaries is made of small tiles
and at high velocity the body goes through it
here is my config of all bodies:
const config = {
inertia: Infinity, // do not spin
friction: 0, // X*100% stop on hit
frictionAir: 0, // X*100% slow on move
restitution: 0.5, // bounce X*100% on hit
collisionFilter: this.level.getCollisionFilter(), // default collision filter
isStatic
}
...
getCollisionFilter (key = null) {
switch (key) {
case 'fly':
return {
category: 0x0008,
mask: 0xFFFFFFF1,
group: -1
}
case 'items':
return {
category: 0x0004,
mask: 0xFFFFFFF1,
group: -1
}
case 'woda':
return {
category: 0x0002,
mask: 0xFFFFFFFF,
group: -1
}
default:
return {
category: 0x0001,
mask: 0xFFFFFFFF,
group: 0
}
}
}
```
woda means water if it's of any relevance
this is between the default and woda
The problem is that matter.js you are using has no continuous collision detection. It has been a feature request for a few years. Now that doesn't mean there is nothing you can do. There is some code in the issue description itself which is probably the cheapest way of fixing issue with going through rectangular boundaries:
It detects if a body is outside the world bounds and then reverses the velocity and translates the body back
Alternatively, this post gives a few ideas.
If you want to implement something yourself, I'll try to explain continuous collision detection algorithm.
Basically, for each moving object in your scene you have to calculate moment of next collision within the fraction of the frame 0<t0<1, then advance positions to this moment t0 within the frame, update velocities due to collision and proceed further to the next collision t0<t1<1, until you reach time of tn=1 (end of frame), making sure you don't get stuck in a the middle of the frame due to rounding of calculation or "cornered" objects. For spherical colliders, that is usually done by using capsule vs capsule (for pairs of objects) intersection and capsule vs box for the boundaries.
You can also cheat by having multiple hidden frames at a slower speed:
take highest object velocity
take smallest object collider radius
divide highest velocity by smallest radius of your colliders and get 'slowdown scale' rounded it to an integer
slow down all the objects in the scene by that integer 'slowdown scale' and update scene 'slowdown scale' times, without redrawing the screen
redraw the screen only once with result of 'slowdown scale' updates and you should get same positions as without slowdown, but respecting collisions
Good luck colliding!
First time posting here. Tried to look for topics previously to help.
I'm using Visual Basic, but so far I've been able to follow C# and just translate into VB.
I would like collision without tiles. Smooth movement without any sort of snapping. I already have the movement down, and my sprites stop at the edges of the screen.
I've read I could use Bounds and Intersects, which I have tried. When I apply an IF statement to the arrow keys each time they are pressed, using Bounds and Intersects (I just prevent sprite movement if it is intersecting), it works for ONE key. I move left into an object, and I stop. If I apply the IF to all keys, it will work the first time. Say I move left into an object, the IF statement checks if the Intersects is true or not and acts accordingly.
Now I want to move right, away from the object. I can't since my sprite is ALREADY colliding with the object, since each arrow key is programmed to NOT move if there is Intersection. I see perfectly why this happens.
The code I currently have: (Each arrow key has the same code, altered to it)
If Keyboard.GetState(PlayerIndex.One).IsKeyDown(Keys.Right) And rBlockBounds.X <=
graphics.GraphicsDevice.Viewport.Width - rBlockBounds.Width = True Then
If rBlockBoundBoxBounds.Intersects(rObstructBounds) Then
rBlockBounds.X += 0
rBlockBoundBoxBounds.X = rBlockBounds.X - 1
Else
rBlockBounds.X += 1
rBlockBoundBoxBounds.X = rBlockBounds.X - 1
End If
End If
rBlockBounds is my sprite As Rectangle
rBlockBoundBoxBounds is another Rectangle (1 pixle bigger than rBlockBounds) used as a Hit Box more or less that moves with rBlockBounds, and is the thing doing the collision checking
rObstructBounds is the stationary object that I'm moving my Sprite into.
Anyone have suggestions on how I can make this work?
Since I myself program in C#, not VB I can not code your solution but instead I can explain a better way of approaching it.
What you want to do is prevent the two rectangles from ever intersecting. To do this you will need to implement a move method into your code which can check if the two tiles are colliding. Here is a C# example:
public bool MoveX(float distance) // Move Player Horizontally in this example
{
rBlockBounds.X += distance;
if(rBlockBoundBoxBounds.Intersects(rObstructBounds)
{
rBlockBounds.X -= distance;
return false;
}
return true;
}
Which essentially means that if you run into an object you will be pushed out of it. Since it occurs in one tick you won't get any jutty back-and-front animations.
And that should do what you want. You can test this out and then implement it for y-coordinates as well.
Also, you might notice I've made the function return a bool. This is optional but allows you to check if your player has moved or not.
Note if you teleport an object into another one it will cause problems so remember to implement this every time you move anything.
But that should do what you want.
Edit
Note since your objects are not in a tiled grid, you will need to move lots of time in very small steps.
Something like this:
public bool MoveX(float distance) // Move Player Horizontally in this example
{
rBlockBounds.X += distance;
if(rBlockBoundBoxBounds.Intersects(rObstructBounds)
{
rBlockBounds.X -= distance;
return false;
}
return true;
}
public bool MoveX(float distance, int repeat)
{
for(int i=0; i < repeat; i++)
{
rBlockBounds.X += distance;
if(rBlockBoundBoxBounds.Intersects(rObstructBounds)
{
rBlockBounds.X -= distance;
return false;
}
}
return true;
}
Where the second one will take multiple steps. Here is why you would use it:
MoveX(500); // Will move 500 right. Could easily skip over objects!
MoveX(5, 100); // Will move 5 right one hundred times
// ^ This will take more time but will not skip object
Similarly for yours you could do this:
MoveX(3); // If contact object will be max 3 pixels away
MoveX(1, 3); // If contact object will be max 1 pixels away
MoveX(0.5f, 6); // If contact object will be max 0.5 pixels away
Now I am guessing all your x, y positions are integers. If so you could get away doing the second call and come exactly next to each other. If not you would do the third call.
Hope this helped.
I have a method that I use to render little map using tiles, but when I finish rendering and I want to make a translation changing "transY" variable using different method nothing happens, so I must call RenderTesture() again to make it. How can I do this withot unnecessary rendering because it can slow down application when I use larger number of tiles?
void RenderTexture ()
{
MakeCurrent ();
GL.Clear((int)All.ColorBufferBit | (int)All.DepthBufferBit);
GL.MatrixMode(All.Modelview);
GL.LoadIdentity();
GL.Translate(-transX, transY, -10);
for (int i = 0; i < tileRows; i++)
{
for (int j = 0; j < tileColumns; j++)
{
GL.BindTexture(All.Texture2D, textureIds [i*tileColumns + j]);
GL.EnableClientState(All.VertexArray);
GL.EnableClientState(All.TextureCoordArray);
GL.PushMatrix ();
GL.Translate(j*2, -i*2, 0);
GL.VertexPointer(3, All.Float, 0, frontV);
GL.TexCoordPointer(2, All.Float, 0, frontT);
GL.DrawArrays (All.TriangleFan, 0, 4);
GL.PopMatrix ();
}
}
GL.DisableClientState(All.VertexArray);
GL.DisableClientState(All.TextureCoordArray);
SwapBuffers ();
}
If anybody have advice for me, I'll be very grateful!
Thanks in advance!
The bottleneck lies, most likely, in the amount of state changes (GL.BindTexture) and the amount of draw calls you are making (GL.DrawArrays). In general, you should draw as much as possible in a single draw call.
The simplest approach wold be to use a "texture atlas":
combine all your tile textures into a single large texture (this is the "texture atlas")
combine all your tile vertices into a single vertex array
call GL.BindTexture once to bind the texture atlas
call GL.DrawArrays once to render all tiles
So how do you render different tile textures? Simple: you change the vertex texture coordinates to point to the correct tile inside the texture atlas.
A single 1024x1024 can hold 256 distinct 64x64 tiles. Depending on the amount of distinct tiles in your game, you might have to use multiple texture atlases. Moreover, depending on the size of your map, you might wish to split it into "regions" with separate vertex arrays for each (you don't want to render 1 million tiles every frame if your monitor can only display 1000 tiles.)
On its own, this will give a measurable performance boost. Once this is working, you can get a second large boost by storing your vertex arrays on the GPU via Vertex Buffer Objects (VBOs).
Thank you very much!
The "Texture atlas" strategy can be very good idea. I've implemented that last night and it looks like rendering is getting speed. I've reduce loading of NxM tiles using separate textures, by loading one big NxM tiles bitmap using single texture and I've implemented method to change vertex array (in regard to new bitmap dimensions - NxM)
public void UpdateFrontVertex(int rowNumber, int columnsNumber)
{
for (int i = 0; i < 12; i++) {
if (i % 3 == 0)
frontVertex [i] = defaultFrontVertex[i] * rowNumber; // x-axis
else if (i % 3 == 1)
frontVertex [i] = defaultFrontVertex[i] * columnsNumber; // y-axis
else if (i % 3 == 2)
frontVertex [i] = defaultFrontVertex[i]; // z-axis
}
}
After that, I've got my map!!!
I still cannot compare performances before that implementation and now because I have to make changes for panning and zooming functionalities to work with that new rendering strategy.
For example, I've used
//zoom in
transY = (transY * 2 + 1);
transX = (transX * 2 + 1);
//zoom out
transX = ((transX - 1) / 2);
transY = ((transY - 1) / 2);
for zooming calculations to figure out which tile is my central tile, and after that to load all rounding tiles.
Thank you again for great help, I'll proceed now with panning and zooming implementation.
I'm trying to write a basic game using Apple's Sprite Kit framework. So far, I have a ship flying around the screen, using SKPhysicsBody. I want to keep the ship from flying off the screen, so I edited my update method to make the ship's velocity zero. This works most of the time, but every now and then, the ship will fly off the screen.
Here's my update method.
// const int X_MIN = 60;
// const int X_MAX = 853;
// const int Y_MAX = 660;
// const int Y_MIN = 60;
// const float SHIP_SPEED = 50.0;
- (void)update:(CFTimeInterval)currentTime {
if (self.keysPressed & DOWN_ARROW_PRESSED) {
if (self.ship.position.y > Y_MIN) {
[self.ship.physicsBody applyForce:CGVectorMake(0, -SHIP_SPEED)];
} else {
self.ship.physicsBody.velocity = CGVectorMake(self.ship.physicsBody.velocity.dx, 0);
}
}
if (self.keysPressed & UP_ARROW_PRESSED) {
if (self.ship.position.y < Y_MAX) {
[self.ship.physicsBody applyForce:CGVectorMake(0, SHIP_SPEED)];
} else {
self.ship.physicsBody.velocity = CGVectorMake(self.ship.physicsBody.velocity.dx, 0);
}
}
if (self.keysPressed & RIGHT_ARROW_PRESSED) {
if (self.ship.position.x < X_MAX) {
[self.ship.physicsBody applyForce:CGVectorMake(SHIP_SPEED, 0)];
} else {
self.ship.physicsBody.velocity = CGVectorMake(0, self.ship.physicsBody.velocity.dy);
}
}
if (self.keysPressed & LEFT_ARROW_PRESSED) {
if (self.ship.position.x > X_MIN) {
[self.ship.physicsBody applyForce:CGVectorMake(-SHIP_SPEED, 0)];
} else {
self.ship.physicsBody.velocity = CGVectorMake(0, self.ship.physicsBody.velocity.dy);
}
}
}
At first, I used applyImpulse in didBeginContact to push the ship back. This made the ship bounce, but I don't want the ship to bounce. I just want it to stop at the edge.
What is the right way to make the ship stop once it reaches the edge? The code above works most of the time, but every now and then the ship shoots off screen. This is for OS X—not iOS—in case that matters.
Check out this link...
iOS7 SKScene how to make a sprite bounce off the edge of the screen?
[self setPhysicsBody:[SKPhysicsBody bodyWithEdgeLoopFromRect:self.frame]]; //Physics body of Scene
This should set up a barrier around the edge of your scene.
EDIT:
This example project from Apple might also be useful
https://developer.apple.com/library/mac/samplecode/SpriteKit_Physics_Collisions/Introduction/Intro.html
Your code is not clear in what the velocity variables represent. Keep in mind that if the velocity is too high your ship will have travelled multiple points between updates. For example, your ship's X/Y is at (500,500) at the current update. Given a high enough velocity, your ship could be at (500,700) at the very next update. If you had your boundary set at (500,650) your ship would already be past it.
I suggest you do a max check on velocity BEFORE applying it to your ship. This should avoid the problem I outlined above.
As for bouncy, bouncy... did you try setting your ship's self.physicsBody.restitution = 0; ? The restitution is the bounciness of the physics body. If you use your own screen boundaries, then I would recommend setting those to restitution = 0 as well.
Your best bet would be to add a rectangle physics body around the screen (boundary). Set the collision and contact categories of the boundary and player to interact with each other. In the didBeginContact method you can check if the bodies have touched and, if they have, you can call a method to redirect the ship.
Your problem is that your update method may not be checking the location frequently enough before the ship gets off screen.
This will help you to define you screen edges in Swift.
self.physicsBody = SKPhysicsBody ( edgeLoopFromRect: self.frame )
Suppose I have an array of objects Ball that are floating around in the canvas, and if an object is clicked, it will disappear. I am having a hard time thinking how to know if an object is clicked. Should I use for loop to loop through if the mouse position is within the area of those objects? But I am afraid that will slow down the progress. What is a plausible algorithm to achieve this?
Keep track of the various centre points and radius of the Balls, and whenever a mouse click happens, calculate the distance of the mouse co-ordinates to the other balls centres. If any distance comes out to be within the radius of the particular ball, that means that, that particular ball was clicked.
public class Ball {
private Point centre;
private int radius;
public boolean isInVicinityOf(int x, int y)
{
// There are faster ways to write the following condition,
// but it drives the point I'm making.
if(Math.hypot(centre.getX() - x, centre.getY() - y) < radius)
return true;
return false;
}
// ... other stuff
}
Here's a code for checking if mouse click happened on any ball:
// Returns the very first ball object which was clicked.
// And returns null if none was clicked.
public Ball getBallClicked(Ball[] balls, MouseEvent event)
{
for (Ball ball : balls)
{
if(ball.isInVicinityOf(event.getX(), event.getY()))
{
return ball;
}
}
return null;
}
There are many other ways to go about implementing the same thing, like by using Observer pattern and others, but above is one of those approach.
Hope it helps.
Use void mouseClicked() it then specify its cordinates on the screen. You can specify what you want to do with the object in an if-statement in that void.