Trouble understanding Vectors, my object gets stuck after a few iterations - java

Im trying to write a class that draws a square shape with 4 vertexes. I want each vertex to have its own velocity and path for each iteration in the drawloop. It seems to work for a few iterations until it gets "stuck" and Im having trouble understanding why that is. Any help or information regarding this is helpful, I suspect I dont have a full grasp of using vectors properly.Heres an image of when the code is running.
void draw() {
p.display();
//Stop loop setting
if (loop == 0) {
noLoop();
}
}
//----------------------------------------------------------------//
class Pillar
{
PVector v1Velocity,v2Velocity,v3Velocity,v4Velocity,
v1Pos,v2Pos,v3Pos,v4Pos,
v1End,v2End,v3End,v4End,
v1Acceleration,v2Acceleration,v3Acceleration,v4Acceleration,
origin;
float life,scale,randDegrees1,randDegrees2,randDegrees3,randDegrees4,maxVelocity;
Pillar (float _x, float _y, float _scale) {
scale = _scale; // scale of pillar
origin = new PVector(_x,_y); //pillar point of origin
v1Pos = new PVector(origin.x-(scale*1.5),origin.y); //vertex 1 start left
v2Pos = new PVector(origin.x,origin.y-scale); //vertex 2 start top
v3Pos = new PVector(origin.x+(scale*1.5),origin.y); //vertex 3 start right
v4Pos = new PVector(origin.x,origin.y+scale); //vertex 4 start bottom
v1End = new PVector(origin.x+random(50,200),origin.y-random(50,200));
v2End = new PVector(origin.x+random(50,200),origin.y-random(50,200));
v3End = new PVector(origin.x+random(50,200),origin.y-random(50,200));
v4End = new PVector(origin.x+random(50,200),origin.y-random(50,200));
randDegrees1 = random(360);
randDegrees2 = random(360);
randDegrees3 = random(360);
randDegrees4 = random(360);//Fixa denna.
v1Velocity = new PVector(cos(radians(randDegrees1)),sin(radians(randDegrees1)));
v2Velocity = new PVector(cos(radians(randDegrees2)),sin(radians(randDegrees2)));
v3Velocity = new PVector(cos(radians(randDegrees3)),sin(radians(randDegrees3)));
v4Velocity = new PVector(cos(radians(randDegrees4)),sin(radians(randDegrees4)));
maxVelocity = 5;
life = 100;
}
void calculateVector() {
v1Acceleration = PVector.sub(v1End,v1Pos);
v1Velocity.add(v1Acceleration);
v2Acceleration = PVector.sub(v2End,v2Pos);
v2Velocity.add(v2Acceleration);
v3Acceleration = PVector.sub(v3End,v3Pos);
v3Velocity.add(v3Acceleration);
v4Acceleration = PVector.sub(v4End,v4Pos);
v4Velocity.add(v4Acceleration);
v1Acceleration.setMag(life);
v2Acceleration.setMag(life);
v3Acceleration.setMag(life);
v4Acceleration.setMag(life);
v1Velocity.limit(maxVelocity);
v2Velocity.limit(maxVelocity);
v3Velocity.limit(maxVelocity);
v4Velocity.limit(maxVelocity);
v1Pos.add(v1Velocity);
v2Pos.add(v2Velocity);
v3Pos.add(v3Velocity);
v4Pos.add(v4Velocity);
life -= 1;
}
void display () {
beginShape();
stroke(0,0,0,50);
vertex(v1Pos.x,v1Pos.y);
vertex(v2Pos.x,v2Pos.y);
vertex(v3Pos.x,v3Pos.y);
vertex(v4Pos.x,v4Pos.y);
endShape(CLOSE);
calculateVector();
}
}

Related

Moving objects in a series of set directions

I am new to coding and struggling with a project. I do not know Java well.
My aim is as follows: monitoring and optimization of a concrete delivery service for construction sites by the company operator (concrete plant and truck suppliers).
I should have a concrete plant, two trucks and several sites that are created thanks to the user's click. The operator can have at any time the vision of the trucks of his company that deliver concrete to the worksites located in a given geographical area. And the number of sites evolves (= click of the user hard the screen).
Variables:
Concrete plant -> Coordinates (xCoord, yCoord) + size;
Site(arraylist) -> Coordinates (site.x, site.y or destination.x, destination.y in the lorry class) + size;
Lorry (x2) -> Coordinates (location.x, location.y); size; origin; destination.
Actions of a lorry:
move to a site (1)
wait about 3 seconds when it reaches the site
go to the next site of the list (2) (+wait 3secs)
go back to the concrete plant after it reaches 2 sites (wait 3 secs)
go to the next site (3), then (4), go back to concrete plant etc...
(basically it does 2 sites and comes back, 2 site and comes back etc... And it cannot go to a site that has already been delivered).
It would be good also to have the logo of the site change once it has been reached by a lorry.
Choice of the lorry: I got 2 lorries and the choice on which lorry to go needs to be made by:
if its free (not already on route to a site);
if it is full (has done 0 or 1 site, or hasn't done 2 sites);
the closest one ( measure the distance).
Interaction with HTML:
I was thinking if possible to somehow measure the distance made by each lorries and display it on the HTML screen (and save the data with a keypress if possible).
So I started by looking if I can maybe add a lorry (don't know if its the right part to start on, maybe the actions would be better). And i tried telling it that if the siteNumber is under 2 it goes through the list of sites, but if not the new destination is the concrete plant. But it doesn't work.
So that's my script so far (I have replaced the images of the concrete, site and lorries by ellipses and rectangles so you can run it):
/*preload = "factory_12.png";*/
/*preload = "sign.png";*/
/*preload = "simple_truck.png";*/
Lorry lorry;
//PImage concretePlant;
//PFont aFont;
int xCoord;
int yCoord;
ArrayList<Site> sites;
int siteSize = 30;
void setup() // What is called once at the beginning
{
size (500, 500);
//concretePlant = loadImage("factory_12.png");
//aFont = createFont("IndustrialRevolution-Regular", 12);
//textFont(aFont);
xCoord = int(width/2);
yCoord = int(height/2);
//Creating empty Array List where store sites objects
sites = new ArrayList<Site>();
//Adding first site
sites.add(new Site(random(width), random(height), siteSize));
//storing lorries
lorry = new Lorry(xCoord, yCoord);
}
void draw() // Draw the background and concrete plant
{
background (235, 247, 255); //light blue background, not in draw as it wouldn't allow the site image to stay
//image(concretePlant, xCoord, yCoord, 60, 60);
ellipse(xCoord, yCoord, 60, 60);
//fill(1);
//text("Concrete Plant", xCoord-20, yCoord+70);
//Calling the sites
for (int i = sites.size () - 1; i>=0; i--) {
Site site = sites.get(i);
site.displaySites();
}
//calling the lorry functions
lorry.updateLorry();
}
void mousePressed() {
sites.add(new Site(mouseX, mouseY, siteSize));
}
class Site
{
float x,y;
float size;
//PImage picture;
Site (float xin, float yin, float sin)
{
x = xin;
y = yin;
size = sin;
//picture = loadImage("sign.png");
}
void displaySites()
{
//image(picture, x, y, 60, 60);
rect(x, y, 60, 60);
}
}
class Lorry
{
PVector location1;
PVector location2;
PVector concretePlant;
//PVector velocity;
//PImage mixer;
boolean changeDirection;
int siteNumber = 0;
Site destination;
Lorry(float xCoord, float yCoord)
{
concretePlant = new PVector(xCoord, yCoord); //Initial start point
location1 = new PVector(xCoord, yCoord); //Initial start point
location2 = new PVector(xCoord, yCoord); //Initial start point
//velocity = new PVector(2, 2);
//mixer = loadImage("simple_truck.png");
destination = sites.get(siteNumber);
changeDirection = false;
}
void displayLorry()
{
//image(mixer, location1.x, location1.y, 30, 30);
//image(mixer, location2.x, location2.y, 30, 30);
ellipse(location1.x, location1.y, 30, 30);
ellipse(location2.x, location2.y, 30, 30);
}
void Move()
{
float xdir1 = destination.x - location1.x;
float ydir1 = destination.y - location1.y;
PVector dir1 = new PVector (xdir1, ydir1);
dir1.normalize();
location1.add(dir1);
print("1going");
float xdir2 = destination.x - location2.x;
float ydir2 = destination.y - location2.y;
PVector dir2 = new PVector (xdir2, ydir2);
dir2.normalize();
location2.add(dir2);
print("2going");
}
void checkProgress()
{
for (int siteNumber = 0; siteNumber < 2; siteNumber = siteNumber++);
if (dist(destination.x, destination.y, location1.x, location1.y) < 1) {
if (siteNumber <sites.size() -1) {
siteNumber++; // siteNumber = siteNumber + 1;
destination = sites.get(siteNumber);
changeDirection = true;
println("1reached final site");
} else {
destination.x = concretePlant.x;
destination.y = concretePlant.y;
println ("1back to home");
}
println("1progress checked ");
}
if (dist(destination.x, destination.y, location2.x, location2.y) < 1) {
if (siteNumber <sites.size() -1) {
siteNumber++; // siteNumber = siteNumber + 1;
destination = sites.get(siteNumber);
changeDirection = true;
println("2reached final site");
} else {
destination.x = concretePlant.x;
destination.y = concretePlant.y;
println ("2back to home");
}
println("2progress checked ");
}
}
void updateLorry()
{
displayLorry();
Move();
checkProgress();
}
}

Android draw ball trail

There are balls in my app that just fly through display. They draws as I want. But now I want to draw the trail behind them.
All I could make is just drawing by canvas.drawPath something like following picture:
But it is not what I want. It should have pointed tail and gradient color like this:
I have no idea how to make it. Tried BitmapShader - couldn't make something right. Help, please.
Code:
First of all, there is Point class for position on display:
class Point {
float x, y;
...
}
And trail is stored as queue of Point:
private ConcurrentLinkedQueue<Point> trail;
It doesn't matter how it fills, just know it has size limit:
trail.add(position);
if(trail.size() > TRAIL_MAX_COUNT) {
trail.remove();
}
And drawing happened in DrawTrail method:
private void DrawTrail(Canvas canvas) {
trailPath.reset();
boolean isFirst = true;
for(Point p : trail) {
if(isFirst) {
trailPath.moveTo(p.x, p.y);
isFirst = false;
} else {
trailPath.lineTo(p.x, p.y);
}
}
canvas.drawPath(trailPath, trailPaint);
}
By the way, trailPaint is just really fat paint :)
trailPaint = new Paint();
trailPaint.setStyle(Paint.Style.STROKE);
trailPaint.setColor(color);
trailPaint.setStrokeWidth(radius * 2);
trailPaint.setAlpha(150);
I see you want to see a gradient on the ball path, you could use something like this
int x1 = 0, y1 = 0, x2 = 0, y2 = 40;
Shader shader = new LinearGradient(0, 0, 0, 40, Color.WHITE, Color.BLACK, TileMode.CLAMP);
trailPaint = new Paint();
trailPaint.setShader(shader);
This is what you should change your trailPaint to and see if it works.
provided from here.
I found solution. But still think it is not the best one.
First of all there are my class fields used for that task.
static final int TRAIL_MAX_COUNT = 50; //maximum trail array size
static final int TRAIL_DRAW_POINT = 30; //number of points to split the trail for draw
private ConcurrentLinkedQueue<Point> trail;
private Paint[] trailPaints;
private float[][] trailPoss, trailTans;
private Path trailPath;
Additionally to trailPath object I used PathMeasure object to split path to multiple equal parts.
After filling trail array object added call of trail calculating function.
lastTrailAdd = now;
trail.add(pos.Copy());
if (trail.size() > TRAIL_MAX_COUNT) {
trail.remove();
}
FillTrail();
Then my FillTrail function.
private void FillTrail() {
trailPath.reset();
boolean isFirst = true;
for(Point p : trail) {
if(isFirst) {
trailPath.moveTo(p.x, p.y);
trailPoss[0][0] = p.x;
trailPoss[0][1] = p.y;
isFirst = false;
} else {
trailPath.lineTo(p.x, p.y);
}
}
PathMeasure path = new PathMeasure(trailPath, false);
float step = path.getLength() / TRAIL_DRAW_POINT;
for(int i=0; i<TRAIL_DRAW_POINT; i++) {
path.getPosTan(step * i, trailPoss[i], trailTans[i]);
}
}
It separated from drawing thread. Next code is drawing function.
private void DrawTrail(Canvas canvas) {
if(trail.size() > 1) {
float prevWidthHalfX = 0f, prevWidthHalfY = 0f, prevX = 0f, prevY = 0f;
Path trailStepRect = new Path();
boolean isFirst = true;
for (int i = 0; i < TRAIL_DRAW_POINT; i++) {
float currWidthHalf = (float) (radius) * i / TRAIL_DRAW_POINT / 2f,
currWidthHalfX = currWidthHalf * trailTans[i][1],
currWidthHalfY = currWidthHalf * trailTans[i][0],
currX = trailPoss[i][0], currY = trailPoss[i][1];
if (!isFirst) {
trailStepRect.reset();
trailStepRect.moveTo(prevX - prevWidthHalfX, prevY + prevWidthHalfY);
trailStepRect.lineTo(prevX + prevWidthHalfX, prevY - prevWidthHalfY);
trailStepRect.lineTo(currX + currWidthHalfX, currY - currWidthHalfY);
trailStepRect.lineTo(currX - currWidthHalfX, currY + currWidthHalfY);
canvas.drawPath(trailStepRect, trailPaints[i]);
} else {
isFirst = false;
}
prevX = currX;
prevY = currY;
prevWidthHalfX = currWidthHalfX;
prevWidthHalfY = currWidthHalfY;
}
}
}
Main point of this is drawing trail by parts with different paints. Closer to ball - wider the trail. I think I will optimise it, but it is allready work.
If you want to watch how it looks just install my app from google play.

Sprites array merges the when rendering sprites

Sprite bucketImage, background, r1, r2, r5,
r10, r20, r50, r100, r200, r500, k1, k2, k5, k10, k20, k50;
I create objects in the method called spawnRaindrop(). I have an array of sprites and I want to sprites were changed in the cycle as it is now, it works, but the images are merged with each other.
sprites = new Sprite[15];
r1 = new Sprite(atlas.findRegion("r1"));
r1.flip(false, true);
r2 = new Sprite(atlas.findRegion("r2"));
r2.flip(false, true);
r5 = new Sprite(atlas.findRegion("r5"));
r5.flip(false, true);
r10 = new Sprite(atlas.findRegion("r10"));
r10.flip(false, true);
r20 = new Sprite(atlas.findRegion("r20"));
r20.flip(false, true);
r50 = new Sprite(atlas.findRegion("r50"));
r50.flip(false, true);
r100 = new Sprite(atlas.findRegion("r100"));
r100.flip(false, true);
r200 = new Sprite(atlas.findRegion("r200"));
r200.flip(false, true);
r500 = new Sprite(atlas.findRegion("r500"));
r500.flip(false, true);
k1 = new Sprite(atlas.findRegion("k1"));
k1.flip(false, true);
k2 = new Sprite(atlas.findRegion("k2"));
k2.flip(false, true);
k5 = new Sprite(atlas.findRegion("k5"));
k5.flip(false, true);
k10 = new Sprite(atlas.findRegion("k10"));
k10.flip(false, true);
k20 = new Sprite(atlas.findRegion("k20"));
k20.flip(false, true);
k50 = new Sprite(atlas.findRegion("k50"));
k50.flip(false, true);
sprites[0] = r1;
sprites[1] = r2;
sprites[2] = r5;
sprites[3] = r10;
sprites[4] = r20;
sprites[5] = r50;
sprites[6] = r100;
sprites[7] = r200;
sprites[8] = r500;
sprites[9] = k1;
sprites[10] = k2;
sprites[11] = k5;
sprites[12] = k10;
sprites[13] = k20;
sprites[14] = k50;
Create game object
private void spawnRaindrop() {
Rectangle raindrop = new Rectangle();
raindrop.x = MathUtils.random(0, 800 - 100);
raindrop.y = 480;
raindrop.width = 100;
raindrop.height = 100;
raindrops.add(raindrop);
lastDropTime = TimeUtils.nanoTime();
}
Create and draw array sprite
game.batch.draw(bucketImage, bucket.x, bucket.y);
for (Rectangle raindrop : raindrops) {
for (int i = 0; i < sprites.length - 1; i++) {
game.batch.draw(sprites[i], raindrop.x, raindrop.y);
}
}
game.batch.end();
RESULT:
I attached the picture, and it can be seen that the images accumulate on each other
It looks like your problem is that you are using the same raindrop.x and raindrop.y coordinates for all sprites!
for (Rectangle raindrop : raindrops)
{
for (int i = 0; i < sprites.length - 1; i++)
{
// The following will draw ALL sprites at the same location!
game.batch.draw(sprites[i], raindrop.x, raindrop.y);
}
}
What you can try is to create a new class called (for example): Raindrops and then in this class maintain a single x,y coordinate for each individual image:
class Raindrop
{
Vector2 coordinates;
Sprite sprite;
}
Then in your spawnRaindrop method, create an array of these Raindrop's and an individual (random?) image for each.
EDIT: I wrote the following code directly here without testing anything, so it will most likely have some errors, but nothing you shouldn't be able to fix yourself...
// This goes into your initialisation method
String regions[] = {"r1", "r2", "r5", "r10", "etc etc etc"}
Raindrop raindrops[] = new Raindrop[15];
for ( int i = 0; i < raindrops.length; i++ )
{
raindrop[i] = new Raindrop();
raindrop[i].coordinate.x = MathUtils.random(screenWidth);
raindrop[i].coordinate.y = MathUtils.random(screenHeight);
raindrop[i].sprite = atlas.findRegion(regions[(int)MathUtils.random(regions.length)]);
}
Then your main loop should look something like this:
game.batch.draw(bucketImage, bucket.x, bucket.y);
for ( Raindrop raindrop : raindrops )
{
game.batch.draw(raindrop.sprite, raindrop.coordinate.x, raindrop.coordinate.y);
}
game.batch.end();

Drawing curves using libgdx

I'm using libgdx trying to draw some curves using this doc.
But when I render, its just a straight line, any ideas why it doesn't curve?
I'm assuming myCatmull.valueAt should populate correct points on curve.
public class IABezier {
Vector2[] points = new Vector2[100];
public IABezier() {
Vector2[] dataSet = new Vector2[2];
dataSet[0] = new Vector2(10.0f, 10.0f);
dataSet[1] = new Vector2(20.0f, 20.0f);
CatmullRomSpline < Vector2 > myCatmull = new CatmullRomSpline < Vector2 > (dataSet, true);
for (int i = 0; i < 100; ++i) {
points[i] = new Vector2();
myCatmull.valueAt(points[i], ((float) i) / ((float) 100 - 1));
}
}
public void draw(ShapeRenderer sRenderer) {
sRenderer.begin(ShapeType.Line);
sRenderer.identity();
for (int i = 0; i < 100 - 1; ++i) {
sRenderer.line(points[i], points[i + 1]);
}
sRenderer.end();
}
}
Rendered ..
A catmullrom spline requires at least four samples. So you'll have to add a few more samples to see the actual curve.
Vector2[] dataSet = new Vector2[6];
dataSet[0] = new Vector2(10.0f, 10.0f);
dataSet[1] = new Vector2(20.0f, 20.0f);
dataSet[2] = new Vector2(20.0f, 10.0f);
dataSet[3] = new Vector2(10.0f, 20.0f);
dataSet[4] = new Vector2(15.0f, 15.0f);
dataSet[5] = new Vector2(25.0f, 25.0f);
Here's an example which you can copy, paste and run.

What is the correct way of creating textures for a map with Libgdx without tmx?

I am making a top down style game using LibGdx that I want to be randomly generated each new game load.
I am using a sprite sheet with 8 x 8 sprites inside that need to be combined into 16 x 16 tiles. (I'm doing this to get more natural looking levels. I can explain this more if needed.)
I already have the algorithm to generate the array for what tile should be what.
But i'm stuck on how I should handle the tile classes.
I have this class called Tile
import com.badlogic.gdx.graphics.g2d.Sprite;
public class Tile extends Sprite{ // Should I use sprite??? Seems wrong..
public byte id;
public static Tile[] tiles = new Tile[256];
public static Tile grass = new GrassTile(0);
public Tile(int id) {
this.id = (byte) id;
if (tiles[id] != null)
throw new RuntimeException("Tile Already Exists....");
tiles[id] = this;
}
}
And I want to have multiple classes that exened this class for each tile. For example this is grass.
import com.badlogic.gdx.graphics.g2d.Sprite;
public class Tile extends Sprite{
public byte id;
public static Tile[] tiles = new Tile[256];
public static Tile grass = new GrassTile(0);
public Tile(int id) {
this.id = (byte) id;
if (tiles[id] != null)
throw new RuntimeException("Tile Already Exists....");
tiles[id] = this;
}
}
Should these classes be extended off of a sprite? Or some other class from libgdx?
Also Keep in mind these tiles are going to be 16 x 16 that are made up of 4 smaller 8x8 sections of the sprite sheet.
A great example provided by the Libgdx github page shows you how to achieve this by generating a TileMapLayer. Assigning cells to the layer and then adding the layer to the map.
This snippet of code will help you achieve what you want. The original documentation is here
More documentation here: Libgdx Tile-maps
public void create () {
float w = Gdx.graphics.getWidth();
float h = Gdx.graphics.getHeight();
camera = new OrthographicCamera();
camera.setToOrtho(false, (w / h) * 320, 320);
camera.update();
cameraController = new OrthoCamController(camera);
Gdx.input.setInputProcessor(cameraController);
font = new BitmapFont();
batch = new SpriteBatch();
{
tiles = new Texture(Gdx.files.internal("data/maps/tiled/tiles.png"));
TextureRegion[][] splitTiles = TextureRegion.split(tiles, 32, 32);
map = new TiledMap();
MapLayers layers = map.getLayers();
for (int l = 0; l < 20; l++) {
TiledMapTileLayer layer = new TiledMapTileLayer(150, 100, 32, 32);
for (int x = 0; x < 150; x++) {
for (int y = 0; y < 100; y++) {
int ty = (int)(Math.random() * splitTiles.length);
int tx = (int)(Math.random() * splitTiles[ty].length);
Cell cell = new Cell();
cell.setTile(new StaticTiledMapTile(splitTiles[ty][tx]));
layer.setCell(x, y, cell);
}
}
layers.add(layer);
}
}
// for top down camera view
renderer = new OrthogonalTiledMapRenderer(map);
}

Categories