I'm learning libgdx by adding some more features to the open source jumper game from Mario Zechner. I'm trying to make some platforms with an angle and run into the problem of collision detection of rotated rectangles.
I followed this solution and used Polygons along with my rectangle bounds.
For testing purposes I don't set an angle yet. I just want to verify that bob jumps correctly off the platforms. But for some reason this doesn't work. the bounds are either too far to the left, above the platform, or not there at all. Am I not setting the polygon correctly?
Would it be easier to use Box2d? I don't have any experience with that and I'm wondering if that's overkill for simple platforms.
public PlatformClient(int platformType, float x, float y) {
this.platformType = platformType;
float x1 = x - Platform.PLATFORM_WIDTH/2;
float y1 = y + Platform.PLATFORM_HEIGHT/2;
this.polyBounds = new Polygon(new float[]{x1, y1, x1+Platform.PLATFORM_WIDTH, y1, x1+Platform.PLATFORM_WIDTH, y1-Platform.PLATFORM_HEIGHT, x1, y1-Platform.PLATFORM_HEIGHT});
polyBounds.setPosition(x-Platform.PLATFORM_WIDTH/2, y-Platform.PLATFORM_HEIGHT/2);
}
class Platform {
public static final float PLATFORM_WIDTH = 2f;
public static final float PLATFORM_HEIGHT = 0.35f;
}
In Bob class update the polygon bounds when he moves:
public void update(float deltaTime) {
...
position.add(velocity.x * deltaTime, velocity.y * deltaTime);
bounds.x = position.x - BOB_WIDTH / 2;
bounds.y = position.y - BOB_HEIGHT / 2;
float newX = position.x - BOB_WIDTH / 2;
float newY = position.y - BOB_HEIGHT / 2;
polyBounds.setVertices(new float[]{
newX, newY,
newX+BOB_WIDTH, newY,
newX+BOB_WIDTH, newY-BOB_HEIGHT,
newX, newY-BOB_HEIGHT});
}
In World class:
private void checkPlatformCollisions () {
int len = platforms.size();
for (int i = 0; i < len; i++)
{
PlatformClient platform = platforms.get(i);
if (bob.position.y >= platform.position.y)
{
if(Intersector.overlapConvexPolygons(bob.polyBounds, platform.polyBounds))
{
System.out.println("it overlaps");
// jump off platform
}
}
}
}
EDIT
Thanks to the shape renderer, I was able to set the polygons correctly. I fixed some +,- issues in the code above. But the following code: Intersector.overlapConvexPolygons() still doesn't work (see image). He jumps before the polygons are making contact or he doesn't jump at all.
Any further ideas?
That's how I draw the polygon of Bob and the platforms that clearly overlap.
public void render() {
shapeRenderer.setProjectionMatrix(cam.combined);
shapeRenderer.begin(ShapeType.Line);
for(int i=0; i<world.platforms.size(); i++) {
shapeRenderer.setColor(1, 0, 0, 1);
shapeRenderer.polygon(world.platforms.get(i).polyBounds.getVertices());
shapeRenderer.polygon(world.bob.polyBounds.getVertices());
}
shapeRenderer.end();
}
ok, I solved it by removing
polyBounds.setPosition(x-Platform.PLATFORM_WIDTH/2, y-Platform.PLATFORM_HEIGHT/2);
from the constructor. Now the collision works correctly.
Related
I'm drawing arrows using Java and I can draw them straight but now I need to have the arrows pointing in different directions.
In my current code, I draw a triangle and then a square.
Is there a way to group the two after they've been drawn and then rotate them at a random angle?
Right now I'm only able to rotate the triangle and square separately, causing some messy thing.
void setup() {
size(400, 400);
}
void draw() {
float r = random(24, 64);
background(255);
drawArrow(r);
//drawPlus(r);
saveFrame("dataArrow/plus####.png");
if (frameCount == 100) {
exit();
}
}
void drawArrow(float r){
float base = r * 2;
float xStart = random(1, width-base - 1);
float xEnd = xStart + base;
float k = 0.5 * base;
float y = random(k, width-k);
float middleBase = base/2 + xStart;
float rectSide = 0.5 * base;
float rectX1 = middleBase - rectSide/2;
float rectX2 = middleBase + rectSide/2;
fill(0);
triangle(xStart, y, xEnd, y, middleBase, y - k);
rect(rectX1, y, rectSide, rectSide);
}
not sure if this exactly what you mean but here is how to move things around
push and pop matrix allows you to organize things that should have the same translations
https://processing.org/reference/pushMatrix_.html
https://processing.org/reference/rotate_.html
https://processing.org/reference/translate_.html
basic example
pushMatrix();//start of new translation and rotation things
translate(xAmount,yAmount);//this moves the origin
rotate(angle);//this rotates around origin
//drawing around the point of rotation 0,0 here
//drawing...
popMatrix();//reset all translations and rotations to before
I have a video game in which an arrow moves towards the side where it is pointing, after rotation the arrow, example:
I need to move the sprite To the same direction in which the arrow points after it has been rotation.
A bit of code As I'm trying to do:
int count = 0;
#Override
protected void handleInput() {
if(Gdx.input.justTouched()){
// move to the direction of pointing:
arrow.setPosition(x, y);
}
}
public void update(float dt){
count++;
// rotate sprite:
arrow.setRotation(count);
}
In the book "Beginning Java Game Development with LibGDX" the author makes a game that I think demonstrates the behaviour you want. The game is "Starfish Collector" from chapter 3. The player moves a turtle to collect starfish. The left and right arrow keys rotate the turtle, and the up arrow key moves the turtle forward in the direction he is currently facing.
The source code for the game can be downloaded from the author's Github account here. (I don't know why he put it in a zip file.)
The relevant code looks like this:
#Override
public void update(float dt) {
// process input
turtle.setAccelerationXY(0, 0);
if (Gdx.input.isKeyPressed(Keys.LEFT)) {
turtle.rotateBy(90 * dt);
}
if (Gdx.input.isKeyPressed(Keys.RIGHT)) {
turtle.rotateBy(-90 * dt);
}
if (Gdx.input.isKeyPressed(Keys.UP)) {
turtle.accelerateForward(100);
}
// ...
Where turtle extends some custom classes that extend Actor.
The code for accelerateForward looks like this:
public void accelerateForward(float speed) {
setAccelerationAS(getRotation(), speed);
}
And then the code for setAccelerationAS looks like this:
// set acceleration from angle and speed
public void setAccelerationAS(float angleDeg, float speed) {
acceleration.x = speed * MathUtils.cosDeg(angleDeg);
acceleration.y = speed * MathUtils.sinDeg(angleDeg);
}
Note that this last bit of code is probably exactly what user unexistential was referring to.
(I recommend this book if you're learning LibGDX and game development. It's very good.)
See also:
Beginning Java Game Development with LibGDX by Lee Stemkoski
Book's source code
The simplest way would be to use the sine and cosine of the rotation amount to determine the x and y components of the translation vector.
I resolved with this page: enter link description here
float mX = 0;
float mY = 0;
int velocity = 5;
private float posAuxX = 0;
private float posAuxY = 0;
int count = 0;
public void update(float dt){
count2++;
flecha.setRotation(count2);
if (count2 >= 360){
count2 = 0;
}
position = new Vector2((float) Math.sin(count2) * velocity,
(float) Math.cos(count2 * velocity));
mX = (float) Math.cos(Math.toRadians(flecha.getRotation()));
mY = (float) Math.sin(Math.toRadians(flecha.getRotation()));
position.x = mX;
position.y = mY;
if (position.len() > 0){
position = position.nor();
}
position.x = position.x * velocity;
position.y = position.y * velocity;
posAuxX = flecha.getX();
posAuxY = flecha.getY();
}
flecha.setPosition(posAuxX, posAuxY);
I'm working on a simple game and i need these squareBumpers which simply stands idle and when got hit, collides and reflects the ball. But currently the ball just flies through my squareBumpers. I can only use java awt and swing libraries. Here's the code:
class squareBumper {
private int x = 300;
private int y = 300;
private Color color = new Color(66,139,139);
public void paint(Graphics g) {
Rectangle clipRect = g.getClipBounds();
g.setColor(color);
g.fillRect(x, y, 31, 31);
}
}
class BouncingBall {
// Overview: A BouncingBall is a mutable data type. It simulates a
// rubber ball bouncing inside a two dimensional box. It also
// provides methods that are useful for creating animations of the
// ball as it moves.
private int x = 320;
private int y = 598;
public static double vx;
public static double vy;
private int radius = 6;
private Color color = new Color(0, 0, 0);
public void move() {
// modifies: this
// effects: Move the ball according to its velocity. Reflections off
// walls cause the ball to change direction.
x += vx;
if (x <= radius) { x = radius; vx = -vx; }
if (x >= 610-radius) { x = 610-radius; vx = -vx; }
y += vy;
if (y <= radius) { y = radius; vy = -vy; }
if (y >= 605-radius) { y = 605-radius; vy = -vy; }
}
public void randomBump() {
// modifies: this
// effects: Changes the velocity of the ball by a random amount
vx += (int)((Math.random() * 10.0) - 5.0);
vx = -vx;
vy += (int)((Math.random() * 10.0) - 5.0);
vy = -vy;
}
public void paint(Graphics g) {
// modifies: the Graphics object <g>.
// effects: paints a circle on <g> reflecting the current position
// of the ball.
// the "clip rectangle" is the area of the screen that needs to be
// modified
Rectangle clipRect = g.getClipBounds();
// For this tiny program, testing whether we need to redraw is
// kind of silly. But when there are lots of objects all over the
// screen this is a very important performance optimization
if (clipRect.intersects(this.boundingBox())) {
g.setColor(color);
g.fillOval(x-radius, y-radius, radius+radius, radius+radius);
}
}
public Rectangle boundingBox() {
// effect: Returns the smallest rectangle that completely covers the
// current position of the ball.
// a Rectangle is the x,y for the upper left corner and then the
// width and height
return new Rectangle(x-radius, y-radius, radius+radius+1, radius+radius+1);
}
}
Take a look at the classes that implement the Shape interface. There are ellipses and other shapes, and they all implement a intersects(Rectangle2D) method. It might help you if you don't want to perform intersection yourself.
As for dealing with the collision, well, it depends on the level of accuracy you want. Simply deflecting the ball of edges is quite easy. Just determine whether the collided side of the rectangle is vertical or horizontal, and negate the corresponding velocity component accordingly. If you want to handle the corners, well that is a bit more complicated.
You need to detect when the ball has collided with the bumper. You have the boundingBox() method of BouncingBall, this will get you a rectangle that contains your ball. So you need to check if this rectangle intersects your square bumper (which implies a collision), and then do something with that.
I'm trying to make a java 2d game, and it seems to work out fine in general. The only problem is, that I can't figure out how to place my "delta" time, to make the movements move the same on 30 FPS as on 1000 FPS.
This is my code for the Entity class:
import java.awt.Rectangle;
import map.Tile;
import graphics.Sprite;
public class Entity {
private String name;
private float positionx, positiony; // Current coordinate
private int targetx,targety; // Target coordinate
private double vx, vy; // Current vector
private double lx, ly; // Last vector
private float speed;
private Sprite sprite;
public Entity(String name, int x, int y, Sprite sprite){
this.name = name;
this.speed = 1f;
this.positionx = x;
this.positiony = y;
this.sprite = sprite;
main.Main.e.addEntity(this); // These kind of calls are ugly, and should be fixed.
}
public void remove(){
main.Main.e.removeEntity(this);
sprite.remove();
}
public void setVector(double vx, double vy){
this.vx = vx;
this.vy = vy;
}
public void update(long delta){
//Multiply modifier to make it act the same on 30 fps as 1000 fps.
vx = vx*delta;
vy = vy*delta;
// Calculate vector
double distance = Math.sqrt((vx * vx) + (vy * vy));
if(distance > 0){ // Have we reached the target yet?
vx = ((vx / distance));
vy = ((vy / distance));
}else{
vx = 0;
vy = 0;
}
//Check collision with objects:
Rectangle rx = new Rectangle((int) (vx+positionx), (int)positiony, 32, 32);
Rectangle ry = new Rectangle((int) positionx, (int)(vy+positiony), 32, 32);
for(Entity e : main.Main.e.getEntities()){
if(this != e){
if(isIntersecting(rx, e.getBounds())){
vx = 0; // Disallow x direction.
}
if(isIntersecting(ry, e.getBounds())){
vy = 0; // Disallow y direction.
}
}
}
//Check tiles:
for(Tile t : main.Main.m.getNeighbours(positionx,positiony)){
if(t.isBlocking()){
if(isIntersecting(rx, t.getBounds())){
vx = 0;
}
if(isIntersecting(ry, t.getBounds())){
vy = 0;
}
}
}
//Update the position:
positionx += vx*speed;
positiony += vy*speed;
//Animate:
animate(vx, vy);
}
public boolean isIntersecting(Rectangle r1, Rectangle r2){
return r1.intersects(r2);
}
public Rectangle getBounds(){
return new Rectangle((int) positionx,(int) positiony,32,32);
}
public void setMoveTo(int x, int y){
this.targetx = x;
this.targety = y;
}
//This function is used by the bots, and not on players (they are setting the vector and use update directly):
public void moveTo(long delta){
setVector((targetx-positionx),(targety-positiony));
update(delta);
}
public void animate(double dx, double dy){
sprite.setPosition((int)positionx, (int)positiony);
if(dx > 0){
sprite.setAnimation(0, 7, 100); // Walk right.
}else if(dx < 0){
sprite.setAnimation(1, 7, 100); // Walk left.
}else{
if(lx > 0){
sprite.setAnimation(2, 3, 200); // Stand right.
}else if(lx < 0){
sprite.setAnimation(3, 3, 200); // Stand left.
}
}
lx = dx;
ly = dy;
}
}
The two problems, that I always run into:
1# The game runs differently on 60FPS than on 500FPS.
2# The game runs the same on 60FPS as 500FPS, but my collision screws up, and I can't move closer than 15px from the other object. I think I need to implement something like: If I can't get 10px closer, then move it 10px closer, but I don't know how to implement it.
How can I implement it correctly? That would help a lot!
The easiest way would be to consider that if you want a constant displacement with a constant velocity you can scale all the deltas relative to the delta of 30 FPS like so:
So if you run at 60 FPS but want the same displacement as on 30FPS alpha would be (1/30)/(1/60) = 2
So
Remove vx = vx*delta;
vy = vy*delta;
and change your position update to
alpha = (1.0/30)*delta;
positionx += alpha*vx*speed;
positiony += alpha*vy*speed;
This is only a crude solution, let me know how it works, I will drop in later and update for a more correct solution (taking into account that delta is not always 1/FPS due to rendering and computation taking some time).
Edit: Variable delta will come later. But some optimizations:
You don't need to construct a rectangle in both Y and X for collisiondetection, try drawing two rectangles, if they intersect they do so on both axis. Just create a rectangle from vx + posx, vy+posy and check for intersection with this.
The above should half your collisionchecks. For further optimization consider using a QuadTree an implementation can be found here.
For the problem of "blocky" collision testing (where you stop X pixels from the blocking object). You can do the following, in pseudocode:
if(new position will make this colide)
while(this.position is more than one pixel away from blocking object)
keep moving one pixel
This will make you stop 1px from the target.
I'm making my first game using Java on Android. I need to draw a lot of pixels which together should create a line. My first approach was to make a large array of booleans, create a loop, and draw a pixel when the associated boolean was true.
It wasn't a good idea of course (the array is about 200x300). Now I remember only the position of the first pixel of the line, and every next pixel has to remember his follower. It works pretty well, but when the line gets longer (but still not very long), the efficiency is bad (<20 fps after 4000 frames).
This is the function that I use to draw a line (only one for now). Can anybody help me improve its efficiency?
public void drawLine(Canvas canvas, int beginx, int beginy) {
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.RED);
paint.setStrokeWidth(3);
int x = beginx;
int y = beginy;
while(C.mGrid[x][y].nx != -1) {
//canvas.drawLine(x, y, C.mGrid[x][y].nx, C.mGrid[x][y].ny, paint);
canvas.drawPoint(x, y, paint);
Grid temp = C.mGrid[x][y];
if ((C.mGrid[x][y].nx == x) && (C.mGrid[x][y].ny == y)) break;
x = temp.nx;
y = temp.ny;
}
}
and Grid.java:
package com.qwak.achtung;
public float x = 0,y = 0;
public int px = -1, py = -1, nx = -1, ny = -1;
public Grid(float x, float y) {
this.x = x;
this.y = y;
}
public void set(int px, int py, int nx, int ny) {
this.px = px;
this.py = py;
this.nx = nx;
this.ny = ny;
}
public void setp(int px, int py) {
this.px = px;
this.py = py;
}
public void setn(int nx, int ny) {
this.nx = nx;
this.ny = ny;
}
PS: It looks like this http://c.wrzuta.pl/wi10559/11f7d10b00110e504e25ebd3/0/andek 14 is fps (on my phone (samsung Spica) it run better - 40 but after a while it decreases to 20 and even less) and 983 is number of frames at all.
There is a drawLine method in the canvas object.
Use the example here: How to draw a line in android
canvas.drawLine(0, 0, 20, 20, paint);
If you want to draw a curve. Find the function of the curve. A Parabola for example is x=y^2. You can get points from the curve: 1 = 1, 2 = 4, 3 = 9, 4 = 16... etc.. If your drawing pixel by pixel you can plug in your x and get your y and draw it.
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.RED);
paint.setStrokeWidth(3);
for(int i = beginx; i < CanvasWidth; i++)
{
int x = i;
int y = i * i; //x=y^2
canvas.drawPoint(x, y, paint);
}
To keep a record of points that were visited you could do the following:
class Point
{
int x;
int y;
}
List<Point> points = new List<Point>();
onMove(int newX, int newY)
{
Point p = new Point();
p.x = newX;
p.y = newY;
points.add(p);
}
onDraw()
{
for(Point p : points)
{
canvas.drawPoint(p.x, p.y, paint);
}
}
You want to look into the bresenham algorithm. A bresenham algorithm is a method to draw or rasterize a line. It's a bit different from the subdivision of a grid in a certain angle for example a morton-curve. It's a bit like compute the scalar product for every angle like recall here Traversing a 2D array in an angle.