I am following a guide on how to play a flappy bird clone in the LibGdx framework.
-http://www.kilobolt.com/day-5-the-flight-of-the-dead---adding-the-bird.html
I am currently on the part where the author discusses adding the actual bird and the physics behind the bird. He encapsulates the state of the bird with these instance variables
private Vector2 position;
private Vector2 velocity;
private Vector2 acceleration;
private float rotation; // For handling bird rotation
private int width;
private int height;
and he initializes these instance variables or fields inside the constructor
public Bird(float x, float y, int width, int height) {
this.width = width;
this.height = height;
position = new Vector2(x, y);
velocity = new Vector2(0, 0);
acceleration = new Vector2(0, 460);
}
The author explained that the 460 constant acceleration in the y direction is due to gravity, that is earth's gravity causes an object to speed up by 9.8m/s every second or 9.8m/s^2.
When asked how he determined the 460, the author responded, "Acceleration was experimentally determined. Its value does not change."
My question is how would you go about experimenting for this value? What information would you use. I think really understanding the process behind this experimentation would be valuable for developers who are trying to incorporate gravity in their applications.
I think this 460 would be in terms of the game units, where the author, james, earlier defined as cam.setToOrtho(true, 136, 204);
By "experimentally determined," the author just means trying various values until finding something that worked. There's no math or complex magic here. To experiment with it, just change it and run the program again. If you like what you see, use it. If not, adjust it accordingly.
The number of 9.8 m/s² is just a reference to how Earth's gravity works. It has nothing to do with the actual game's implementation.
You could define what real world size will your pixel represent. Then use kinematic formula to calculate what time will take some object to go to the peek and fall back again. Then measure the time of your game object and try to tune up your gravity the way that jump takes approximately the same time as you calculated.
Related
I am programming a game of sorts which would be kinda long to explain, but in short the player is an ellipse() and follows the mouse around, whilst the rect() is the obstacle that moves down the screen and needs to be dodged by the player, otherwise it's game over. There are multiple rect as I am using an ArrayList to store each obstacle object.
Currently, the player can just pass straight through the rect without anything happening to it. I have tried to solve it multiple times but it got extremely messy and I couldn't understand much due to being extremely new to Java (only 1 week of experience), so I have just placed the empty code below.
tldr; I need to figure out how to get an ellipse/rect collision to work (in its own method). I only have 1 week of Processing/Java experience. I've cut out most of the code that you don't need to look at, mainly just kept the variables used to define the shapes and the code for the shapes just in case you need that. Also, if possible could the collision method could be placed inside the Enemy Class.
Enemy Class (all the variables used to define the rect)
class Enemy {
int enemyNumber; // used to determine enemy type
//VARIABLES FOR ENEMY
boolean redEnemy = false; // determine enemy colour
color enemyColour = color(#B9B9E8); // sets default colour to blue
PVector position, velocity;
float xDist, yDist; // x and y distance for Bar
float smallCircleRad, bigCircleRad; // radius for circles
// **************************************************************************
Enemy() { //CONSTRUCTOR
position = new PVector(width/2, random(-300000, -250));
//println(position.y);
velocity = new PVector(0, 10);
smallCircleRad = 200;
bigCircleRad = 400;
xDist = width;
yDist = 200;
enemyNumber = int(random(1, 6));
}
// **************************************************************************
void redBar(float xPos, float yPos, float xDist, float yDist) {
redEnemy = true;
noStroke();
enemyColour = color(#E38585);
fill(enemyColour);
rect(xPos, yPos, xDist, yDist);
}
void blueBar(float xPos, float yPos, float xDist, float yDist) {
redEnemy = false;
noStroke();
enemyColour = color(#B9B9E8);
fill(enemyColour);
rect(xPos, yPos, xDist, yDist);
}
Player Class (all the variables used to define the ellipse)
class Player {
int r = 50; //player radius
float playerX = width/2; //starting x coordinate
float playerY = height/2+500; //starting y coordinate
float speed = 20; //player speed
float angle; //angle used to calculate trajectory for player
void playerChar() { //method for player model and general rules
stroke(10);
rectMode(CENTER);
fill(playerColour);
ellipse(playerX, playerY, r*2, r*2);
}
Make your life easier by treating the player as a rectangle instead of a circle. You can still draw them as a circle, but for collision detection, use a rectangle. This is called a bounding box and is very popular in collision detection.
Then you can use rectangle-rectangle collision detection, which is much simpler.
Some basic google searches return these results:
Axis-Aligned Bounding Box
What is the fastest way to work out 2D bounding box intersection?
Processing Collision Detection
If for some reason you absolutely need the player to be a circle when calculating the collision, then I'd start by googling something like "circle rectangle collision detection".
If you still can't get it figured out, please post a MCVE in a new question and we'll go from there. Good luck.
I am working on a project in LibGDX, and I am using Scene2D actors for some of my sprites. In this regard, I have a sprite, which is spawning somewhere on the screen and needs to move to another position on the screen. To do this I am using the moveTo(xPos, yPos, duration, interpolation) method in the Actions, to make the move animation.
However, when I use this approach, the actor moves like I told it to, but it only moves in a straight line, from point A to B. I have tried several Interpolation options, like Circle interpolation and such, but it seems only to impact the speed of the animation line.
So now my question: How do I make my animation make a smooth curved line (See picture), from A to B?
I am currently using this code to make the Actions animation:
adultCustomerPointActor.addAction(Actions.sequence(
Actions.moveTo(300, 200, 2f, Interpolation.circle)
));
Thanks in advance for your help :)
It's a geometry problem. Using vectors, find the point halfway between the two points:
vec1.set(bx, by).sub(ax, ay).scl(0.5f).add(ax, ay);
Get another vector that is 90 or 270 to from the vector between the points:
vec2.set(bx, by).sub(ax, ay).rotate90().add(vec1);
This vec2 can be scaled to adjust how extreme curvature of the arc is. If you leave it alone, you'll have a quarter circle. You can also scale it negative to reverse the curvature.
Then add the second vector to the first to find the center point of your arc, which we can call point C.
vec1.set(bx, by).sub(vec2); // CB
vec3.set(ax, ay).sub(vec2); // CA
float angle = vec1.angle(vec3);
Now you need a vector that points from point C to point A. You will rotate this vector until it reaches point B. So you need the angle between CA and CB.
So here's a very simplistic class that implements this. It doesn't account yet for deciding if you want the arc to go up or down and if you want to scale how extreme it looks. You could add those as additional parameters with getters/setters. I haven't tested it, so it may need some debugging.
public class ArcToAction extends MoveToAction {
private float angle;
private final Vector2 vec1 = new Vector2(), vec2 = new Vector2(), vec3 = new Vector2();
#Override
protected void begin () {
super.begin();
float ax = target.getX(getAlignment()); // have to recalculate these because private in parent
float ay = target.getY(getAlignment());
vec1.set(getX(), getY()).sub(ax, ay);
vec2.set(vec1).rotate90();
vec1.scl(0.5f).add(ax, ay);
vec2.add(vec1);
vec1.set(bx, by).sub(vec2); // CB
vec3.set(ax, ay).sub(vec2); // CA
angle = vec1.angle(vec3);
}
protected void update (float percent) {
if (percent >= 1){
target.setPosition(getX(), getY(), getAlignment());
return;
}
vec1.set(vec3).rotate(percent * angle);
target.setPosition(vec1.x, vec1.y, getAlignment());
}
}
If you want to support automatic pooling, you can add a method like this:
static public ArcToAction arcTo (float x, float y, float duration, Interpolation interpolation) {
ArcToAction action = Actions.action(ArcToAction .class);
action.setPosition(x, y);
action.setDuration(duration);
action.setInterpolation(interpolation);
return action;
}
Problem: my player model is supposed to turn into the direction of the last mouse click but instead of turning slowly it spins in all possible ways(Game has an isometric view, the model is supposed to rotate only around the Y-axis but it rotates around the X- and Z-axis too).
Following method(called in render()) is responsible for the turning behavior of the model:
public static void turnUnit(){
if(Gdx.input.isButtonPressed(Input.Buttons.LEFT)){
mX = Gdx.input.getX();
mY = Gdx.input.getY();
angle = (float) (180+Math.atan2(mX-Gdx.graphics.getWidth()/2, mY-Gdx.graphics.getHeight()/2)*(180/Math.PI));
newAngle = ((((currentAngle - angle) % 360) + 540) % 360) - 180;
turning = newAngle/60*turnRate;
currentAngle = currentAngle-turning;
}
TestGround.player.transform.setToRotation(Vector3.Y, currentAngle).setTranslation(posX,0,posZ);
}
And the movement-method(also called in render()):
public static void movement(){
if(northM==true){
TestGround.player.transform.trn(0,0,-1f);
}
if(southM==true){
TestGround.player.transform.trn(0,0,1f);
}
if(westM==true){
TestGround.player.transform.trn(-1f,0,0);
}
if(eastM==true){
TestGround.player.transform.trn(1f,0,0);
}
posX = TestGround.player.transform.getTranslation(Vector3.X).x;
posY = TestGround.player.transform.getTranslation(Vector3.Y).y;
posZ = TestGround.player.transform.getTranslation(Vector3.Z).z;
}
Tried to use "rotate" in the last line but then it just spins faster.
Also, even though this makes no sense to me but after some testing it seems the movement-method somehow interferes with the turn-method(moving in a certain direction will rotate the model in a certain way).
Am I doing something fundamentally wrong here?
Additional Info:
originally I used simple polling to get all keyboard and mouse input
calculated movement/rotation in one big method and everything worked
fine
decided to use the inputprocessor of libgdx to make the code more readable and open-ended
The Matrix4#getTranslation(Vector3) method will set the specified vector to the translation component of the matrix and return it for chaining. What this means is that the vector you supply as argument to the TestGround.player.transform.getTranslation(vector) method, will be set (read: overwritten) to the translation (position) of the model instance.
So, in the case of the call to:
TestGround.player.transform.getTranslation(Vector3.Y)
This will practically modify the Vector3.Y variable from the default [x:0, y:1, z:0], to whatever the translation component of the matrix is set to. This will result in any other call that uses the Vector3.Y variable (like your call to setToRotation) to behave differently.
To fix that you can modify the last few lines to:
Vector3 pos = new Vector3();
TestGround.player.transform.getTranslation(pos);
posX = pos.x;
posY = pos.y;
posZ = pos.z;
Note that you should move the creation of the Vector3 out of the method and therefor might as well remove the posX, posY and posZ members in favor of the pos member.
So, you might be wondering two questions:
Why does the getTranslation method modify its arguments? This is because libGDX is designed to avoid creating garbage, because that will create hick-ups on some platforms, like Android. So instead of creating a new Vector3 every time the method is called, it allows you to specify an instance of that class which you want to reuse. You will see this pattern throughout the lib at multiple places because of this reason.
Why is it even possible to modify Vector3.Y, making it useless and cause all kind of problems? This is because the Vector3 class is mutable and does not encapsulate its members. So practically it allows you to do vector.x += 3; instead of forcing you to call vector.setX(vector.getX() + 3);. This is both for readability and performance reasons (although the latter might vary on your target platform). Also, java does not support something comparable to const.
I'm making apong game, in a boolean method in the Paddle class I want to determine if the ball touching any of the two paddles, I'm struggling of finding the proper logic...
here are the variables:
// instance variables
private Screen theScreen;
private MyroRectangle theRectangle;
private int topLeftX;
private int topLeftY;
// constants
private final int HEIGHT = 100; //the paddle's fixed height
private final int WIDTH = 5; //the paddle's fixed width
private final int PIXELS_PER_MOVE = 20; //the number of pixels a paddle can move either up or down in one timestep
here is the method: * this method is just to determine if the ball touch or not it doesn't do anything with bounce the ball back
public boolean isTouching(Ball b)
{
boolean t = false;
if ((theScreen.getWidth()-(b.getX() + b.getRadius())) >= theScreen.getWidth()-theRectangle.getCenterX() )
{
t= true;
}
return t;
also I tried:
if ((b.getX() > theRectangle.getCenterX()/2) && (b.getY() < theRectangle.getCenterY()/2))
==========
** the methods of the ball class that might be needed:
getX()
getY()
getRadius()
==============
** the Rectangle class:
getCenterX()
getCenterY()
===============
** the Screen class:
getWidth()
getHeight()
I just want to determine at least on of the conditions then I can figure out the rest of them.
In my junior year in college I worked on a Collision detection system algorithm for the windows phone. It is hardly perfect but it was EXTREMELY efficient and can be adapted to a majority of games.
The way that it worked was pretty simple. There were two types of objects; Collidable objects (such as enemies or buildings) and Objects that you wish to check for collisions with these collidable objects.
I had this idea when I was going through a data structures class and we spoke about Linked Lists. I thought what if each link was a collidable object that you could stick your game objects that were already created in it. Then as the game objects moved around you would have a lightweight way of checking their locations for collisions. Thus my system was born.
Basically what it comes down to is using
C (or the distance between to points) = SqrRoot(A^2 + B^2) - radius of ball
this formula should look very familiar to you.
You can see the full answer on this question:
Java More Resourceful Collision Detection
This problem can be seen as solving the question if two 2d-areas, the paddle (a rectangle) and the ball (a circle) intersect. You can just google/wiki formulas for that.
If you don't want to go into the math for solving the problem through geometry, package java.awt.geom contains classes that can do the calculations for you, namely java.awt.Area. You would just create Area instances for paddle and ball and then call the intersects() method to know if they collided.
In Java using the acm.graphics GPen is there any way to move the entire drawn sequence of lines? I've read the manual thoroughly and I'm beginning to think it's not possible which brings me to my second question. Are there any other graphics objects in Java that work very similar to a pen that can also be moved. The reason I'm asking is because I've been working on a graphing program that allows mouse gestures to be used to pan around and zoom in and out. After building functionality for implicit functions I realized simply clearing the drawing board and redrawing everything is not going to cut it anymore so I really need to work on more efficient ways to handle intermediate changes of the graph without having to recalculate everything. For example with this or similar code:
GPen p = new GPen();
p.setLocation(100,100); //places the pen on the canvas at 100, 100
p.drawLine(-50,0); //draw a line left 50 pixels
p.drawLine(50,-50); //draw a line right and up 50 pixels each
p.drawLine(0,50); //draw a line down 50 pixels
This would result in a simple right triangle who's bottom right most point is at 100, 100 on a particular canvas. What I need to do is be able to move this same drawn sequence of lines relative to one another to another origin. What I hoping for is a class that has separate methods for setLocation() and move() where setLocation() controls pen position and move() would move the entire object around.
Ok so having received almost no attention on here I've came to the conclusion that such a method just needs to be written from scratch and went ahead and did that. I'm not entirely sure how helpful posting my proprietary code would be but in the event that anybody could use it I'll post the basic idea of it. Since Pen utilities are essentially a bunch of lines and lines are a bunch of from and to's I created an object that I called FPen (for FunctionPen) that accepts the instructions for from and to. While defining FPen you pass it where to start and how far to go however many times you need and that's it. Once you've passed these instructions I created another method called returnGPen(Color c) which will on call use the instructions it has on hand and generate the desired GPen object. When you want to move the entire GPen you can then create a method called adjustOrigin(double oX, double oY); which will calculate a change from a previously recorded origin and this new one and go through the list of instructions and adjust them appropriately.
My needs for this Class are strictly for my Graphing program and are not entirely finished either but it does work for most purposes.
import acm.graphics.GPen;
import java.awt.Color;
import java.util.ArrayList;
public class FPen{
private double relativeCenterX;
private double relativeCenterY;
private ArrayList<Double> fromX = new ArrayList<Double>();
private ArrayList<Double> fromY = new ArrayList<Double>();
private ArrayList<Double> distX = new ArrayList<Double>();
private ArrayList<Double> distY = new ArrayList<Double>();
public FPen(double rX, double rY, double z){
relativeCenterX = rX;
relativeCenterY = rY;
}
public void adjustOrigin(double cX, double cY){
double changeX = relativeCenterX-cX;
double changeY = relativeCenterY-cY;
for(int i = 0; i < fromX.size(); i++){
fromX.set(i,fromX.get(i)+changeX*zoom);
fromY.set(i,fromY.get(i)-changeY*zoom);
}
relativeCenterX = cX;
relativeCenterY = cY;
}
public void clear(){
fromX.clear();
fromY.clear();
distX.clear();
distY.clear();
}
public void drawLine(double fX, double fY, double tX, double tY){
fromX.add(fX);
fromY.add(fY);
distX.add(tX);
distY.add(tY);
}
public GPen returnGPen(Color c){
GPen pen = new GPen();
pen.setColor(c);
for(int i = 0; i < fromX.size(); i++){
pen.setLocation(fromX.get(i),fromY.get(i));
pen.drawLine(distX.get(i),distY.get(i));
}
return pen;
}
}
Of course a unexpected nice thing that came out of this was the idea that I can now quickly benchmark different drawing routines by creating different methods for each and calling what I'm interested in.