Currently iam programming on a game where you move a spaceship and try to avoid asteroids. The spaceship should move when the user touches it and so follow the finger movement of the user.
The spaceship is a sprite that moves arround with:
if (Gdx.input.isTouched()) {
x = Gdx.input.getX() - width / 2;
y = -Gdx.input.getY() + height / 2;
}
The problem that i'm having right now is that the user can teleport the spaceship by touching the screen. How can i fix this? Is it possible to set a touch region?
Calculate a unit vector direction from the ship to the touch point and multiply that by a speed. You need to convert touch coordinates to world coordinates by unprojecting with the camera.
private static final float SHIP_MAX_SPEED = 50f; //units per second
private final Vector2 tmpVec2 = new Vector2();
private final Vector3 tmpVec3 = new Vector3();
//...
if (Gdx.input.isTouched()) {
camera.unproject(tmpVec3.set(Gdx.input.getX(), Gdx.input.getY(), 0)); //touch point to world coordinate system.
tmpVec2.set(tmpVec3.x, tmpVec3.y).sub(x, y); //vector from ship to touch point
float maxDistance = SHIP_MAX_SPEED * Gdx.graphics.getDeltaTime(); //max distance ship can move this frame
if (tmpVec2.len() <= maxDistance) {
x = tmpVec3.x;
y = tmpVec3.y;
} else {
tmpVec2.nor().scl(maxDistance); //reduce vector to max distance length
x += tmpVec2.x;
y += tmpVec2.y;
}
}
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
So I am making my bullets go to a point and travel further. Only its acting really really weird. Its like its thinking that the 0,0 location is at the top left instead of the bottom left.
This is the code:
float speed = 100;
Vector2 direction;
Vector2 thisPos = new Vector2(getX(), getY());
Vector2 mousePos;
public Bullet(){
super();
setSprite(sprite);
setX(0); setY(0);
float dx = Gdx.input.getX() - getX();
float dy = Gdx.input.getY() - getY();
mousePos = new Vector2(Gdx.input.getX(), Gdx.input.getY());
direction = new Vector2(dx, dy);
//sprite.setRotation(direction.angle(thisPos));
direction.nor();
}
public void update(){
Vector2 dirAd = new Vector2(direction);
thisPos.x += dirAd.x * speed * Gdx.graphics.getDeltaTime();
thisPos.y += dirAd.y * speed * Gdx.graphics.getDeltaTime();
setPosition(thisPos.x, thisPos.y);
super.update();
}
I hope someone can help me what I did wrong with this.
Gdx.input.getX() and getY() by definition do treat the top left as 0,0. From the getX() method:
"The screen origin is the top left corner."
You may need to look into the camera's unproject method, which takes the screen input coordinates and translates them to "world" space.
I'm trying to understand these code:
/*
* File: BouncingBallWalls.java
* ---------------------
* This is exercise 15 in chapter 4 of "The Art and Science of Java."
* It requires me to write a program that makes an animated bouncing
* ball on the screen, bouncing off the window edges.
*/
import java.awt.*;
import acm.program.*;
import acm.graphics.*;
public class BouncingBallWalls extends GraphicsProgram {
public void run() {
GOval ball = new GOval (getWidth()/2 - BALL_SIZE/2, getHeight()/2 - BALL_SIZE, BALL_SIZE, BALL_SIZE); /* Centers the ball */
ball.setFilled(true);
ball.setFillColor(Color.BLUE);
ball.setColor(Color.BLUE);
add(ball);
double dx = (getWidth()/N_STEPS);
double dy = (getWidth()/N_STEPS);
while(true) {
ball.move(dx, dy); /* Movement for the ball */
pause(PAUSE_TIME);
if (ball.getY() > getHeight() - BALL_SIZE) { /* Each "if" statement reverses the direction of the ball on one */
dy = dy * -1; /* axis if it hits a boundry */
}
if(ball.getX() > getWidth()- BALL_SIZE) {
dx = dx * -1;
}
if(ball.getY() < 0) {
dy = dy * -1;
}
if(ball.getX() < 0) {
dx = dx * -1;
}
}
}
private static final double N_STEPS = 1000;
private static final double PAUSE_TIME = 2;
private static final double BALL_SIZE = 50.0;
}
I understand everything except the following, why do you divide your gameWidth by N_STEPS? and what is N_STEPS?
double dx = (getWidth()/N_STEPS);
double dy = (getWidth()/N_STEPS);
private static final double N_STEPS = 1000;
Reference: http://tenasclu.blogspot.co.uk/2012/12/first-few-days-of-learning-to-program.html
You divide screen size by N_STEPS to get dx and dy, which represent the distance you want the ball to move during each loop. N_STEPS defines the movement in terms of the available screen width so that the relative movement/speed is the same regardless of screen size.
Another way of looking at N_STEPS, is that it controls the smoothness and speed of the ball. It does so in a way that makes the smoothness and speed consistent regardless of screen size. A higher N_STEPS will result in smoother/slower ball movement per loop.
Note that your code:
double dx = (getWidth()/N_STEPS);
double dy = (getWidth()/N_STEPS);
Should probably:
double dx = (getWidth()/N_STEPS);
double dy = (getHeight()/N_STEPS);
Basically what the tuorial is demonstrating is animating the motion of the ball. Now in each iteration of the while loop the ball has to move a certain distance in x and a certain distance in y. This incremental change is denoted as dx and dy.
To calculate how much the ball should move in each increment, the total distance the ball should move is divided by the number of iterations. This is to create the sensation of smooth movement. If the number of steps was too low and the total distance needed to travel was too high, then the ball would jump from one spot to the next.
N-STEPS is the distance in pixels/unit on screen. Different devices have different sizes. Say you have a device that has a screen of 800 pixels in width. Regardless of the device size, you may want to make an imaginary grid. Say if we divide the size by 20, we get 40 (800/20=40). This gives us 40 pixels or 1 unit. So, if we move something, we can move 40 pixels or 1 unit at a time horizontally. This helps when dealing with different screen sizes.
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.