Centering map or camera 2D game - java

I've tried so many solutions that it's possible that my code is a bit mixed up, but whatever I try, it just won't work.
Basically I made a map with Tiled, where my player can run around and bump into stuff. I want the whole map to be visible for the whole time (it's 20 by 15, 64 pixels a tile). The camera doesn't need to move around or follow the player, it has to stay still at the center of the map.
The problem is that the map only shows in the upper right corner of the screen. When I centered the camera to the map itself it messed up the collission detection, (bumping into trees while they were not visible & walking through visible trees). So what I want to do is center the map to 0,0 where my camera also is (at least I think..).
Another thing I'd like to accomplish is that the size of the map gets resized to match different mobile phones. Tried to accomplish this with the stretchviewport, but haven't been able to test this.
public class PlayScreen implements Screen {
TiledMap map;
OrthogonalTiledMapRenderer mapRenderer;
OrthographicCamera cam;
float unitScale = 1 / 64f;
OrthogonalTiledMapRenderer renderer = new OrthogonalTiledMapRenderer(map, unitScale);
Viewport viewport;
public void show() {
map = new TmxMapLoader().load("maps/map.tmx");
mapRenderer = new OrthogonalTiledMapRenderer(map);
cam = new OrthographicCamera(Gdx.graphics.getWidth() / 2, Gdx.graphics.getHeight() / 2);
cam.setToOrtho(false);
viewport = new StretchViewport(1280, 960, cam);
bounds = new ArrayList<Rectangle>();
for(int i = 0; i < 20; i++){
for(int j = 0; j < 15; j++){
TiledMapTileLayer cur = (TiledMapTileLayer) map.getLayers().get(1);
Cell cell = new Cell();
Vector3 center = new Vector3(cur.getWidth() * cur.getTileWidth() / 2, cur.getHeight() * cur.getTileHeight() / 2, 0);
cam.position.set(Gdx.graphics.getWidth() / 2, Gdx.graphics.getHeight() / 2, 0);
cam.update();
if(cur.getCell(i,j) != null){ //null = first layer != --> if its not
cell = cur.getCell(i, j);
System.out.println(i + ", " + j + ", " + cell.getTile().getId());
bounds.add(new Rectangle(i * 64, j * 64, 64 , 64));
}
}
}
public void render(float delta) {
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
mapRenderer.setView(cam);
mapRenderer.render();
cam.position.set(0, 0, 0);
cam.update();
batch.setProjectionMatrix(cam.combined);
batch.begin();
batch.draw(player.getCurrentFrame(), player.getPosition().x , player.getPosition().y);
player.update();
for(int i = 0; i < bounds.size(); i++){
if(bounds.get(i).overlaps(player.getBounds())){
int x = (int)bounds.get(i).x / 64;
int y = (int)bounds.get(i).y / 64;
TiledMapTileLayer cur = (TiledMapTileLayer)map.getLayers().get(1);
Cell cell = cur.getCell(x, y);
if(cell.getTile().getProperties().containsKey("blocked")){
System.out.println("bush");
}
player.reAdjust();
}
}
batch.end();
}
public void resize(int width, int height) {
viewport.update(width, height);
}

Nevermind, I deleted: cam.position.set(0, 0, 0); and everything seems to work just fine. Guess I already made some changes what caused it to work, just didn't see it cause this was still around.

Related

node's are not intersection while using loops inside of an array?

My problem is wherever i click a node appears and for the second click another node appears with connected edge...so i want that When i click at any location, the node should be generated at the closest grid intersection point. I tried using loops.
and i'm trying to do that without "class"
int n_partition=10;
int length = 101;
PVector[] position = new PVector[length];
int BallNum;
void setup() {
size(600, 360);
background(255);
}
void draw() {
fill(255);
grid();
fill(0);
}
void mousePressed(){
stroke(0);
BallNum++;
position[BallNum]= new PVector(mouseX, mouseY);
circle(position[BallNum].x, position[BallNum].y, 10);
if (BallNum > 1) {
line(position[BallNum].x,position[BallNum].y,position[BallNum-
1].x,position[BallNum-1].y);
line(position[1].x,position[1].y,position[BallNum].x,position[BallNum] .y);
}
for (int i = 0; i < position[BallNum].length; ++ i) {
position[BallNum] = position[BallNum].get(i);
position[BallNum] = position[BallNum].get((i+1) % position[BallNum].length);
line(position[BallNum].x, position[BallNum].y,
position[BallNum].x, position[BallNum].y);
}
}
I EXPECT THE NODE SHOULD GO TO THE CLOSEST INTERSECTION.
You've to calculate the nearest position of the mouse to a point on the grid. For that you've to know the width (tile_width) and the height (tile_height) of cell.
The index of the cell can be calculated by the dividing the mouse position to the size of a tile and round() the result to an integral value (e.g. round(mouseX / (float)tile_width)).
Don't draw anything in int the mousePressed callback. The only thing you've to do there is to add a pint to the list:
void mousePressed(){
int tile_width = width / n_partition; // adapt this for your needs
int tile_height = height / n_partition;
int x = round(mouseX / (float)tile_width) * tile_width;
int y = round(mouseY / (float)tile_height) * tile_height;
position[BallNum]= new PVector(x, y);
BallNum++;
}
All the drawing has to be done in draw(). Draw the lines and points in separate loops:
void draw() {
background(255);
grid();
// draw the lines in a loop
strokeWeight(3);
stroke(0, 0, 255);
for (int i = 0; i < BallNum; ++ i) {
int i2 = (i+1) % BallNum;
line(position[i].x, position[i].y, position[i2].x, position[i2].y);
}
// draw balls in a loop
strokeWeight(1);
stroke(0, 0, 0);
fill (255, 0, 0);
for (int i = 0; i < BallNum; ++i) {
circle(position[i].x, position[i].y, 10);
}
}
Note, the scene is consecutively redrawn in every frame. Before the scene is drawn, the entire window has to be "cleared" by background().
See the result:

processing - how to plot a scatter graph with x/y axis bigger than width/height of window

So i have code witch generates a list of the numbers in the recaman sequence and plots them (with 0,0 at bottom left using translate(0,height); scale(1,-1); ).
My problem is it only shows a small part of the graph i want to plot. For example, i want to be able to have 10,000 on the y axis and x axis as well as points using those numbers, but keeping to 500,500 window size.
I want to plot a graph bigger than 500,500, the window size.
how do i do this, if it is possible?
Create a PGraphics object of size (10000, 10000).
Render your points into this (you can call every Processing drawing method on a PGraphics object).
Draw the PGraphics object at different locations within the window to simulate panning within the graph.
The following example shows how you could do the above, with mouse panning functionality and a static graph (instantiated and populated in setup()).
import processing.core.PApplet;
import processing.core.PGraphics;
public class Prototype extends PApplet {
public static void main(String[] args) {
PApplet.main(Prototype.class);
}
int xOffset = 0, yOffset = 0;
int xOffsetP, yOffsetP;
int mouseDownX, mouseDownY;
boolean move = false;
PGraphics graph;
#Override
public void settings() {
size(500, 500);
}
#Override
public void setup() {
graph = createGraphics(2000, 2000); // Create graph 2000x2000px
graph.beginDraw();
graph.background(255);
graph.fill(0);
for (int i = 0; i < 1000; i++) { // Adds 1000 random points to graph
graph.ellipse(random(2000), random(2000), 3, 3);
}
for (int i = 0; i < graph.height; i += 50) { // Adds Y-axis labels
graph.text(i, 5, graph.height - i);
}
graph.line(0, 0, 1999, 0); // Graph edge/border
graph.line(0, 1999, 1999, 1999);
graph.line(0, 0, 0, 1999);
graph.line(1999, 0, 1999, 2000);
graph.endDraw();
}
#Override
public void draw() {
background(255);
if (move) {
xOffset = mouseDownX - mouseX + xOffsetP;
yOffset = mouseY - mouseDownY + yOffsetP;
xOffset = constrain(xOffset, 0, graph.width - width); // Optional
yOffset = constrain(yOffset, 0, graph.height - height); // Optional
}
image(graph, -xOffset, yOffset - graph.height + height);
fill(255, 0, 0);
text("X Offset: " + xOffset, 0, 10);
text("Y Offset: " + yOffset, 0, 25);
}
#Override
public void mousePressed() {
move = true;
mouseDownX = mouseX;
mouseDownY = mouseY;
}
#Override
public void mouseReleased() {
move = false;
xOffsetP = xOffset;
yOffsetP = yOffset;
}
}
Result (in a 500x500 window):

Wrong center of screen coordinates

I'm coding an Android game and I'm trying to put the character in the middle of the screen (X axis).
In order to get the middle of the screen I get the screen width withe the following command:
int phoneWidth = Resources.getSystem().getDisplayMetrics().widthPixels;
Then I divide phoneWidth by two and hoped that the character would appear in the middle of the screen but it appears slightly to the right.
This is the code that I use:
public void drawCharacter() {
charImg = new Texture("pika.PNG");
charSprite = new Sprite(charImg);
float ahaha = Gdx.graphics.getWidth();
charPosX = (float)phoneWidth/ 2;
}
#Override
public void render() {
ch.stop();
double elapsedSeconds = ch.getSeconds();
checkLevel();
handleObstacles();
scrollTimer = scrollTimer + Gdx.graphics.getDeltaTime() / 2;
if (scrollTimer > 1.0f)
scrollTimer = 0.0f;
sprite.setV(scrollTimer);
sprite.setV2(scrollTimer + 2);
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
charSprite.setPosition(charPosX, charPosY);
for (int i = 0; i < obstacles.size(); i++) {
obstacleSprites.get(i).setPosition(obstacles.get(i).getPosX(), obstacles.get(i).getPosY());
}
spriteBatch.begin();
sprite.draw(spriteBatch);
charSprite.draw(spriteBatch);
for (int i = 0; i < obstacleSprites.size(); i++) {
obstacleSprites.get(i).draw(spriteBatch);
}
spriteBatch.end();
moveCharacter();
moveObstacle();
}
Does anyone know where this error come from?
The left-hand edge of your sprite will be in the middle of the screen.
Subtract half the sprite width from half the screen width to draw the sprite centered horizontally.

Libgdx Scaling coordinates for different devices

I have made a simple game where you click on a object and it should dissapear. It works fine on desktop with the dimensions 240 x 480 but on my phone the dimensions are wider like 1920 x 1080 so the touch down coordinates are different so on desktop it might log the touch 100 x 50 but if i tapped the same place on phone it would be 400 x 200 so i just want to scale them or use the same.
private double WidthScale = (272 / Gdx.graphics.getWidth());
private double HeightScale = (408 / Gdx.graphics.getHeight());
private Array<Rectangle> rockets;
private long lastDropTime = 0;
private float tap_X = 0;
private float tap_Y = 0;
public GameRenderer() {
cam = new OrthographicCamera();
cam.setToOrtho(false, 408, 272);
batch = new SpriteBatch();
rockets = new Array<Rectangle>();
spawnRocket();
}
public void render(){
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
cam.update();
batch.setProjectionMatrix(cam.combined);
batch.begin();
for(Rectangle rocket : rockets) {
batch.draw(AssetLoader.rocket ,rocket.x, rocket.y,
rocket.width, rocket.height);
}
batch.end();
if (Gdx.input.justTouched()){
tap_X = (int) (Gdx.input.getX() * HeightScale);
tap_Y = (int) ((Gdx.graphics.getHeight()-Gdx.input.getY()) * WidthScale);
Gdx.app.log("MyTag", String.valueOf(tap_X));
Gdx.app.log("MyTag", String.valueOf(tap_Y));
Gdx.app.log("MyTag", String.valueOf(HeightScale));
Gdx.app.log("MyTag", String.valueOf(WidthScale));
}
Iterator<Rectangle> iter = rockets.iterator();
while(iter.hasNext()) {
Rectangle rocket = iter.next();
rocket.y -= 70 * Gdx.graphics.getDeltaTime();
if(rocket.y + 32 < 0) iter.remove();
if (rocket.x < tap_X && tap_X < rocket.x + rocket.width) {
Gdx.app.log("MyTag", "getRekt");
if (tap_Y > rocket.y && tap_Y < rocket.y + rocket.height) {
Gdx.app.log("MyTag", "poo");
iter.remove();
}
}
}
if(TimeUtils.nanoTime() - lastDropTime > 1000000000) spawnRocket();
}
private void spawnRocket() {
Gdx.app.log("MyTag", "Rocket Spawned");
Rectangle rocket = new Rectangle();
rocket.x = MathUtils.random(0 , 272 - 16);
rocket.y = 408 + rocket.height;
rocket.height = 32;
rocket.width = 16;
rockets.add(rocket);
lastDropTime = TimeUtils.nanoTime();
}
In order to work with different screen sizes, you have to deal with viewports, there's an entirely section in libGDX wiki that shows how to work with it. A fast example could be the following (however, I suggest to read the wiki and try others viewports by yourself):
// Declare a viewport object
private Viewport v;
public GameRenderer() {
// initialize after your camera initialization
v = new FitViewport(408, 272, cam); // <- I have use a FitViewport
// but you can use others
// I guess you could remove the setToOrtho() but not too sure...
// ... rest of code
}
You have to properly dispose and update this object *
A thing you should consider is, when you use something like Gdx.input.getX() you are getting a screen current position, you have to transform this coordinate system to your world coordinate system. Wherever you use something like that you have to do the following:
Vector3 v = new Vector3(Gdx.input.getX(), Gdx.input.getY(), 0);
v = cam.unproject(v);
// now v has your coordinate world system and you can properly make use of it
// you can do now something like:
tap_x = (int) v.x;
tap_y = (int) v.y;
Hope you find this useful.

Poor render performance in LibGDX with hexagonal map

So I am making a simple game using LibGDX which involes a 150*150 hexagonal map, and various types of cell, rocky, clear etc.
Problem is when i load the map, my computer almost completely freezes up and any movement thats supposed to be fluid (character moving, button highlights) take 5+ seconds longer than they should.
Here's the relevant code:
public void render(float deltY){
Gdx.gl.glClearColor(255, 255, 255, 100);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
stage.act();
polygonSpriteBatch.begin();
for (int j = 0; j < 150; j++) {
for (int i = 0; i < 150; i++) {
offset = i%2 == 0 ? multipleX/2 : 0;
if (mc.getMap().getRow(i).getTile(j).getTileType().equals(TileType.Rocky)) {
drawCell(Color.BLACK, j, i);}
if (mc.getMap().getRow(i).getTile(j).getTileType().equals(TileType.Clear)) {
drawCell(Color.LIGHT_GRAY, j, i);}
}
}
polygonSpriteBatch.end();
stage.draw();
}
private void drawCell(Color color, int x, int y) {
polySprite = new PolygonSprite(makePoints(color));
polySprite.setX(mc.getMap().getRow(y).getTile(x).getTilePosition().get_x() * multipleX + offset);
polySprite.setY(mc.getMap().getRow(y).getTile(x).getTilePosition().get_y() * multipleY);
polySprite.draw(polygonSpriteBatch);
}
public PolygonRegion makePoints(Color color){
side = 5;
h = CalculateH(side);
r = CalculateR(side);
multipleX = (float)Math.sqrt(3)*side;
multipleY = side+(side/2);
float[] points = { // vertices
x, y,
x+r, y+h,
x+r, y+side+h,
x,y+side+h+h,
x-r, y+side+h,
x-r, y+h};
return new PolygonRegion(new TextureRegion(getTexture(color)),points
, new short[] { //4 triangles using vertices to make hexagon
0, 1, 5,
1, 4, 2,
5, 1, 4,
2, 3, 4});
}
public Texture getTexture(Color color){
Pixmap pix = new Pixmap(1, 1, Pixmap.Format.RGBA8888);
pix.setColor(color);
pix.fill();
textureSolid = new Texture(pix);
return textureSolid;
}
I'm new to coding and LibGDX so there's probably something stupid i'm doing. Is there any way to render the map once and only redraw the polygons if they change?
Thanks
Looking at your code, you are computing a square root for each cell, for each rendering pass.
So your code currently involves more than 22500 square root operations for each frame you render and is creating as many objects, that's quite a lot !
You should compute the points for your hexagons only once.

Categories