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();
Related
I'm learning to use LibGDX and my goal is to create a cube, with which you can control the resolution (number of vertices along each face). I already did that, and managed to use MeshBuilder to make it out of 6 different meshes and then render the resulting Mesh successfully using basic shaders :
Cube Mesh
//creates a square face with a normal vector and resolution number of vertices along any edge of the face
public Mesh createFace(Vector3 normal, int resolution) {
//creates 2 vectors perpendicular to each other and to the vector normal
Vector3 axisA = new Vector3(normal.y,normal.z,normal.x);
Vector3 axis = u.crs(normal, axisA);
Vector3 axisB = new Vector3(u.sqrt(axis.x),u.sqrt(axis.y),u.sqrt(axis.z));
//creates the arrays to hold the vertices and triangles
Vector3[] vertices = new Vector3[resolution * resolution];
//code for triangles
short[] triangles = new short[(resolution - 1) * (resolution - 1) * 6];
int triIndex = 0;
//looping over each vertex in the face
for (int y = 0; y < resolution; y++) {
for (int x = 0; x < resolution; x++) {
int vertexIndex = x + y * resolution;
//vector representing how close to the end of the x or y axis the loop is
Vector2 t = new Vector2(x / (resolution - 1f),y / (resolution - 1f));
//calculates the position of the vertex to place on the face
Vector3 mulA = u.mul(axisA, (2*t.x - 1));
Vector3 mulB = u.mul(axisB, (2*t.y-1));
Vector3 point = u.add3(normal, mulA, mulB);
//point = u.normalize(point);
vertices[vertexIndex] = point;
//puts the vertices into triangles
if (x != resolution - 1 && y != resolution - 1) {
triangles[triIndex + 0] = (short) vertexIndex;
triangles[triIndex + 1] = (short) (vertexIndex + resolution + 1);
triangles[triIndex + 2] = (short) (vertexIndex + resolution);
triangles[triIndex + 3] = (short) vertexIndex;
triangles[triIndex + 4] = (short) (vertexIndex + 1);
triangles[triIndex + 5] = (short) (vertexIndex + resolution + 1);
triIndex += 6;
}
}
}
float[] verticeList = u.vectorToList(vertices);
Mesh m = new Mesh(true, resolution * resolution, triangles.length, new VertexAttribute(Usage.Position,3,"a_Position"));
m.setIndices(triangles);
m.setVertices(verticeList);
return m;
}
//generates a cube Mesh with resolution vertices along each face
public Mesh generateFaces(int resolution, float scale) {
MeshBuilder meshBuilder = new MeshBuilder();
meshBuilder.begin(new VertexAttributes(new VertexAttribute (Usage.Position, 3 ,"a_Position")));
Vector3[] faceNormals = {
new Vector3(0,1*scale,0), //up
new Vector3(0,-1*scale,0), //down
new Vector3(-1*scale,0,0), //left
new Vector3(1*scale,0,0), //right
new Vector3(0,0,1*scale), //forward
new Vector3(0,0,-1*scale) //back
};
for (int i = 0; i < faceNormals.length; i++) {
meshBuilder.part("part"+ Integer.toString(i), GL20.GL_TRIANGLES);
meshBuilder.addMesh(createFace(faceNormals[i], resolution));
}
Mesh mesh = meshBuilder.end();
return mesh;
}
u is just a utilities class i created to store some math functions.
I then render it like so:
#Override
public void render () {
camController.update();
Gdx.gl.glViewport(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
Gdx.gl.glClearColor(0.5f, 0.5f, 0.5f, 0.5f);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
shader.bind();
shader.setUniformMatrix("matViewProj", cam.combined);
//rendering mesh
mesh1.render(shader, GL20.GL_LINE_STRIP);
[...]
}
I now want to make a model out of that mesh where each of the 6 faces will have a different color.
I thus tried to do it using a ModelBuilder following the LibGDX wiki, like so:
public Model generateModel(int resolution, float scale, Color[] colors) {
Vector3[] faceNormals = {
new Vector3(0,1*scale,0), //up
new Vector3(0,-1*scale,0), //down
new Vector3(-1*scale,0,0), //left
new Vector3(1*scale,0,0), //right
new Vector3(0,0,1*scale), //forward
new Vector3(0,0,-1*scale) //back
};
ModelBuilder modelBuilder = new ModelBuilder();
modelBuilder.begin();
for (int i = 0; i < faceNormals.length; i++) {
Mesh mesh = createFace(faceNormals[i], resolution);
MeshPart part = new MeshPart("part"+Integer.toString(i),mesh, 0, mesh.getNumVertices() ,GL20.GL_TRIANGLES);
modelBuilder.node().parts.add(new NodePart(part, new Material(ColorAttribute.createDiffuse(colors[i]))));
}
Model m = modelBuilder.end();
return m;
}
And then i rendered it using a ModelBatch and ModelInstance :
#Override
public void create () {
//creates an environment to handle lighting and such
environment = new Environment();
environment.set(new ColorAttribute(ColorAttribute.AmbientLight,0.4f,0.4f,0.4f,1f));
environment.add(new DirectionalLight().set(0.8f,0.8f,0.8f,-1f,-0.8f,-0.2f));
modelBatch = new ModelBatch();
//handling the inputProcessors of the camera and stage(UI)
multiplexer = new InputMultiplexer();
stage = new Stage();
multiplexer.addProcessor(stage);
scroll = new ScrolledInputProcessor();
multiplexer.addProcessor(scroll);
//camera (3D inputProcessor)
cam = new PerspectiveCamera(67,Gdx.graphics.getWidth(),Gdx.graphics.getHeight());
cam.position.set(10f,10f,10f);
cam.lookAt(0,0,0);
cam.near = 1f;
cam.far = 300f;
cam.update();
camController = new CameraInputController(cam);
multiplexer.addProcessor(camController);
//shaders for every vertex and every pixel(fragment)
shader = new ShaderProgram(Gdx.files.internal("shader/vertexshader.glsl").readString() ,Gdx.files.internal("shader/fragmentshader.glsl").readString());
shader2 = new ShaderProgram(Gdx.files.internal("shader/vertexshader.glsl").readString() ,Gdx.files.internal("shader/fragmentshader2.glsl").readString());
//The 2D box encompassing the screen (UI)
table = new Table();
table.setFillParent(true);
stage.addActor(table);
//skins for UI
skin = new Skin(Gdx.files.internal("uiskin.json"));
//making a slider and dressing it in the skin
Drawable knobDown = skin.newDrawable("default-slider-knob", Color.GRAY);
SliderStyle sliderStyle = skin.get("default-horizontal", SliderStyle.class);
sliderStyle.knobDown = knobDown;
slider = new Slider(3.0f, 70.0f, 1.0f, false, sliderStyle);
table.right().top();
table.add(slider).row();
//creates the unit cube and unit sphere
model = generateModel(res, 1, colors);
instance = new ModelInstance(model);
font = new BitmapFont(Gdx.files.internal("uiskin.fnt"));
batch = new SpriteBatch();
Gdx.input.setInputProcessor(multiplexer);
}
#Override
public void render () {
camController.update();
Gdx.gl.glViewport(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
Gdx.gl.glClearColor(0.5f, 0.5f, 0.5f, 0.5f);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
shader.bind();
shader.setUniformMatrix("matViewProj", cam.combined);
modelBatch.begin(cam);
modelBatch.render(instance, environment);
modelBatch.end();
batch.begin();
font.draw(batch, "Zoom Level : " + zoomLevel, 1000f, 100f);
batch.end();
stage.act(Gdx.graphics.getDeltaTime());
stage.draw();
}
However, when i run the program, nothing is rendered, just the gray void.
Gray void of nothingness
My question is: How do I get my model to render?
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();
}
}
Basically I have made an interface that displays a picture and it has multiple JSliders. Each one has a different function such as blur, brighten, and saturate. I have implemented the sliders in such a way that I override the stateChanged method when adding a new slider. This works fine when I do the sliders individually, however it changes back to the original picture once I use a different slider. I want to make it so that it the picture accumulates the filters on the photo. Any suggestions? Here is an example of one of my sliders.
brightSlider.addChangeListener(new ChangeListener() {
#Override
public void stateChanged(ChangeEvent e) {
JSlider source = (JSlider) e.getSource();
double scaleValue = source.getValue() / 100.0;
Picture newPic = new PictureImpl(picture.getWidth(), picture.getHeight());
//Picture newPic = picture;
Pixel zeroPixel = new ColorPixel(0, 0, 0);
Pixel p;
for (int i = 0; i < picture.getWidth(); i++) {
for (int j = 0; j < picture.getHeight(); j++) {
newPic.setPixel(i, j, zeroPixel);
}
}
for (int i = 0; i < picture.getWidth(); i++) {
for (int j = 0; j < picture.getHeight(); j++) {
if (scaleValue > 0) {
p = picture.getPixel(i, j).lighten(scaleValue);
newPic.setPixel(i, j, p);
} else if (scaleValue < 0) {
p = picture.getPixel(i, j).darken(scaleValue);
newPic.setPixel(i, j, p);
}
}
}
setPic(newPic);
picture_view.setPicture(newPic.createObservable());
}
});
As shown in Image processing with Java 2D, you can create a Map<String, BufferedImageOp> that holds concrete instances of the BufferedImageOp interface.
Map<String, BufferedImageOp> ops = new TreeMap<String, BufferedImageOp>();
ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
ops.put("Gray", new ColorConvertOp(cs, null));
…
Add the Map key set to a JComboBox.
final JComboBox opBox = new JComboBox();
for (String key : ops.keySet()) {
opBox.addItem(key);
}
In the combo's handler, invoke the image operation's filter() method on your target BufferedImage.
String key = (String) opBox.getSelectedItem();
BufferedImageOp op = ops.get(key);
bufferedImage = op.filter(bufferedImage, null);
The image below illustrates "Threshold 64" followed by "Invert". ImageDicer is a complete example.
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.
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);
}