Java/Slick2D Camera not following character - java

For some reason when i make my map bigger then 15 x 25 the camera gets all buggy, at the top part of the map the camera jumps showing the bottom of the map, and at the bottom it jumps to the top.
Here's the code for it:
public int getXOffset(){
int offset_x = 0;
//the first thing we are going to need is the half-width of the screen, to calculate if the player is in the middle of our screen
int half_width = (int) (Game.WINDOW_WIDTH/Game.SCALE/2);
//next up is the maximum offset, this is the most right side of the map, minus half of the screen offcourse
int maxX = (int) (map.getWidth()*32)-half_width;
//now we have 3 cases here
if(player.getX() < half_width){
//the player is between the most left side of the map, which is zero and half a screen size which is 0+half_screen
offset_x = 0;
}else if(player.getX() > maxX){
//the player is between the maximum point of scrolling and the maximum width of the map
//the reason why we substract half the screen again is because we need to set our offset to the topleft position of our screen
offset_x = maxX-half_width;
}else{
//the player is in between the 2 spots, so we set the offset to the player, minus the half-width of the screen
offset_x = (int) (player.getX()-half_width);
}
return offset_x;
}
public int getYOffset(){
int offset_y = 0;
int half_heigth = (int) (Game.WINDOW_HEIGTH/Game.SCALE/2);
int maxY = (int) (map.getHeight()*32)-half_heigth;
if(player.getY() < half_heigth){
offset_y = 0;
}else if(player.getY() > maxY){
offset_y = maxY-half_heigth;
}else{
offset_y = (int) (player.getY()-half_heigth);
}
return offset_y;
}
In my render method i use this:
map.render(-(offset_x%32), -(offset_y%32), offset_x/32, offset_y/32, 33, 19);
Here's a .gif of the problem, I'm jumping up and down in this: http://i.gyazo.com/11efe44d6e872c334533cd3a40ddf2b9.gif

Instead of rendering an offset to your map, try just using
g.translate(camera.x-(width/2),camera.y-(height/2);
It's much more manageable this way, your camera's co-ordinates would be tied to the players.

Related

Processing - rendering shapes is too slow

I have been doing a small little project using Processing, and the effect I wanted to achieve was a kind of "mountains" forming and moving, using Perlin Noise with the noise() function, with 2 parameters.
I was originally using a image for the background, but for illustrational purposes, I made the background black, and it's basically the same effect.
My issue is that I want to have a "history" of the mountains because they should fade away after some time, and so I made a history of PShapes, and draw the history and update it each frame.
Updating it is no issue, but drawing the PShapes seems to take a lot of time, reducing the frame rate from 60 to 10 when the length of the history is 100 elements.
Below is the code I used :
float noise_y = 0;
float noise_increment = 0.01;
// increment x in the loop by this amount instead of 1
// makes the drawing faster, since the PShapes have less vertices
// however, mountains look sharper, not as smooth
// bigger inc = better fps
final int xInc = 1;
// maximum length of the array
// bigger = less frames :(
final int arrLen = 100;
int lastIndex = 0;
PShape[] history = new PShape[arrLen];
boolean full = false;
// use this to add shapes in the history
PShape aux;
void setup() {
size(1280, 720);
}
void draw() {
background(0);
// create PShape object
aux = createShape();
aux.beginShape();
aux.noFill();
aux.stroke(255);
aux.strokeWeight(0.5);
for (float x = 0; x < width + xInc; x = x + xInc) {
float noise = noise(x / 150, noise_y) ;
// get the actual y coordinate
float y = map(noise, 0, 1, height / 2, 0);
// create vertex of shape at x, y
aux.vertex(x, y);
}
aux.endShape();
// push the current one in the history
history[lastIndex++] = aux;
// if it reached the maximum length, start it over ( kinda works like a queue )
if (lastIndex == arrLen) {
lastIndex = 0;
full = true;
}
// draw the history
// this part takes the MOST TIME to draw, need to fix it.
// without it is running at 60 FPS, with it goes as low as 10 FPS
if (full) {
for (int i = 0; i < arrLen; i++) {
shape(history[i]);
}
} else {
for (int i = 0; i < lastIndex; i++) {
shape(history[i]);
}
}
noise_y = noise_y - noise_increment;
println(frameRate);
}
I have tried to use different ways of rendering the "mountains" : I tried writing my own class of a curve and draw lines that link the points, but I get the same performance. I tried grouping the PShapes into a PShape group object like
PShape p = new PShape(GROUP);
p.addChild(someShape);
and I got the same performance.
I was thinking of using multiple threads to render each shape individually, but after doing some research, there's only one thread that is responsible with rendering - the Animation Thread, so that won't do me any good, either.
I really want to finish this, it seems really simple but I can't figure it out.
One possible solution would be, not to draw all the generated shapes, but to draw only the new shape.
To "see" the shapes of the previous frames, the scene can't be cleared at the begin of the frame, of course.
Since the scene is never cleared, this would cause, that the entire view is covered, by shapes over time. But if the scene would be slightly faded out at the begin of a new frame, instead of clearing it, then the "older" shapes would get darker and darker by time. This gives a feeling as the "older" frames would drift away into the depth by time.
Clear the background at the initlization:
void setup() {
size(1280, 720);
background(0);
}
Create the scene with the fade effect:
void draw() {
// "fade" the entire view
blendMode(DIFFERENCE);
fill(1, 1, 1, 255);
rect(0, 0, width, height);
blendMode(ADD);
// create PShape object
aux = createShape();
aux.beginShape();
aux.stroke(255);
aux.strokeWeight(0.5);
aux.noFill();
for (float x = 0; x < width + xInc; x = x + xInc) {
float noise = noise(x / 150, noise_y) ;
// get the actual y coordinate
float y = map(noise, 0, 1, height / 2, 0);
// create vertex of shape at x, y
aux.vertex(x, y);
}
aux.endShape();
// push the current one in the history
int currentIndex = lastIndex;
history[lastIndex++] = aux;
if (lastIndex == arrLen)
lastIndex = 0;
// draw the newes shape
shape(history[currentIndex]);
noise_y = noise_y - noise_increment;
println(frameRate, full ? arrLen : lastIndex);
}
See the preview:

Java - Pixel-Perfect Collision - gap between player and wall

I'm currently working on a Top-Down-Shooter and having some issues with collision.
My world is made of tiles (64x64). The tiles and the entities are rectangles. The player moves with a speed of e.g 2.74 (and not in pixels for smoother movement). But when it comes to the collision between the player (an entity) and a wall i have some issues. To check if there is a collision i take the current position of my player and his movement speed to calculate where his next position would be and if there is any collision. But i check every pixel on the way, so i cant skip an obstacle even if the movement speed is very high. Let's just say the players current position is X:200 Y:200 and he moves 2.74 Pixels a tick in the x direction. My game now checks if there is any collision at X:201 Y:200, X:202 Y:200 or X:202.74 Y:200 and if not moves the player to that position. If I now try to move the player further in the x direction and there is a wall 0.26 Pixels away the player wont move and leave a tiny gap. I tried to calculate the distance between player and wall and add this amount to the players position but for that I need to know which side of the wall the player hits. Also I want the player to be able to move up and down when the wall he hits is in front of him and the other way around.
Here is my collision method (in Java):
public static boolean collision(float ex, float ey, int width, int height) { // ex, ey would be the next position of the player
if (ex < 0 || ex + width > worldWidth || ey < 0 || ey + height > worldHeight) return true; // checks if this position is in the world
int firstTileX = (int) (ex / Tile.TILE_SIZE); // calculates tiles he could possible collide width
int firstTileY = (int) (ey / Tile.TILE_SIZE);
int lastTileX = (int) ((ex + width - 1) / Tile.TILE_SIZE);
int lastTileY = (int) ((ey + height - 1) / Tile.TILE_SIZE);
for (int y = firstTileY; y <= lastTileY; y++) {
if (y < 0) continue; // checks for out of bounds
if (y >= worldTileHeight) break;
for (int x = firstTileX; x <= lastTileX; x++) {
if (x < 0) continue;
if (x >= worldTileWidth) break;
if (tiles[y][x].solid) return true; // if the tile is solid -> collision found
}
}
return false; // no collision found
}
And my movement method:
public void move(float xa, float ya) {
float nx, ny;
while (xa != 0 || ya != 0) {
nx = x;
ny = y;
if (xa != 0) {
if (Math.abs(xa) > 1) { // if the x-speed is greater than 1
nx = x + MathUtil.abs(xa); // returns -1 for negative numbers and 1 for positiv
xa -= MathUtil.abs(xa);
} else { // less than 1
nx = x + xa;
xa = 0;
}
}
if (ya != 0) { // same here
if (Math.abs(ya) > 1) {
ny = y + MathUtil.abs(ya);
ya -= MathUtil.abs(ya);
} else {
ny = y + ya;
ya = 0;
}
}
if (!Level.collision(nx, ny, width, height)) setPosition(nx, ny); // checks if there is an collision and sets the new position if not
else if (!Level.collision(nx, y, width, height)) x = nx; // if there was a collision check if the player can walk in x direction
else if (!Level.collision(x, ny, width, height)) y = ny; // or in y direction
}
}
My problem is the pretty much the same as CoderMusgrove's problem in his post (Pixel-perfect collision and doubles):
Summary & Question
I have a problem where if the speed of an entity isgreater thanthe distance from the tile it is going into, it will leave at least a pixel in between itself and the tile, and I really don't like this. What kind of algorithm could I use that will find the tiniest difference between the entity and the tile?
If you need any additional information, I will be glad to add it.
Thanks for your help!
Easily resolvable by changing your interpretation.
You are retaining a fractional position for the purpose of fine grained speed. Ignore the fraction for the purpose of collision detection and display (if you were to do sub-pixel rendering, do the collision on the subpixel rendering accurarcy level).
int screenX = (int) Math.round(objX);
int screenY = (int) Math.round(objY);
// rendering and collision detection based on rounded position

Drawing rectangles from center of given coordinate

I made a program where user enters number of rectangles to be drawn and coordinates at which the rectangles are drawn. My rectangles are currently drawn like this:
and I want to achieve this:
This is the code I use to draw the rectangles:
int povecaj_kvadrat=0;
for(int x=0;x<broj_kvadrata;x++) {
Rectangle2D.Float kvadrat=new Rectangle2D.Float(brojevi_koordinate[0],brojevi_koordinate[1],50+povecaj_kvadrat,50+povecaj_kvadrat);
ploca.draw((kvadrat));
povecaj_kvadrat=povecaj_kvadrat+15;
}
}
How do I set the coordinates of the rectangles so that they are drawn like in the second image?
You will have to take into account the additional size of each Rectangle, along with its position within the loop to compute the correct coordinates of each rectangle.
The additional size has been moved as a variable (diffSize), so that your loop can use its value.
The difference in coordinates between two iterations will be half this diff size, multiplied by the inverse of the position in the loop, because the lower the increment (x) and the Rectangle size, the bigger the coordinates .
int gap = 0;
int maxNumber = 3;
int diffSize = 20;
int[] coordinates = { 10, 10 };
for (int x = 0; x <= maxNumber; x++) {
Rectangle2D.Float rectangle = new Rectangle2D.Float(
coordinates[0] + ((diffSize / 2) * (maxNumber - x)),
coordinates[1] + ((diffSize / 2) * (maxNumber - x)),
50 + gap, 50 + gap);
g2d.draw((rectangle));
gap = gap + diffSize;
}
Note that I am unsure of the correct behaviour if diffSize is odd (because (diffSize / 2) will be rounded down to the nearest int value), so I would keep an even value for diffSize.

mouse movement FPS style in Java

So I'm trying to implement a simple mouseLook method for exploring a game world in LWJGL. For now I just want it to work on the rotation-Y axis. The movement at first was limited because of the dimensions of the screen stopped the mouse from moving. So i hid the cursor and set the x-position of the mouse to 0 after deltaX is returned. When i wrote it out on paper the calculations seem to be right I think, however when i run it, the rotation keeps snapping back to 0, and creates a jitter effect. How can i solve this?
public void rotate() { //rotate the camera
System.out.println(getGlobalDX() + " " + MouseInfo.getPointerInfo().getLocation().getX());
float speed = 0.03f;
//START OF CODE TO IGNORE
float ratioX = (float)Display.getWidth() / 360;
float ratioY = (float)Display.getHeight() / 360;
float mouseRotX = Mouse.getX() / ratioX;
float mouseRotY = Mouse.getY() / ratioY;
//END OF CODE TO IGNORE
rotY += getGlobalDX() * speed; // add the deltaX of the mouse position X and multiply it by our speed in order to rotate the camera based on the mouse
lockCursor();
}
public float getGlobalDX() { //returns the difference between the current mouse position and the mouse position during the last frame
frames += 1; //add 1 to frames variable every frame
if(frames >= 1.5) { //if 1.5 frames have passed since last method call, run method again. this is to smooth things out since it doesnt work properly every frame
float mouseX = (float) MouseInfo.getPointerInfo().getLocation().getX(); //get x pos of mouse
frames = 0; //set frames to zero
if(lastMouseX != mouseX) { //if the lastmouse position isnt equal to our current mouse position, then continue
if(mouseX == 963) { //if the mouse position is equal to the centered X position of the screen then continue
lastMouseX = (float) MouseInfo.getPointerInfo().getLocation().getX(); //set this variable to the new x position
System.out.println("returning zero"); //debug by checking if this code runs (it does)
return 0; //return 0 since we dont want to undo the position we returned last frame
}
float deltaX = (float) (mouseX - lastMouseX); // difference between current mouse position and last to get the overall change in position
lastMouseX = (float) MouseInfo.getPointerInfo().getLocation().getX(); //set to new x position
MouseInfo.getPointerInfo().getLocation().setLocation(MouseInfo.getPointerInfo().getLocation().getX()/2, MouseInfo.getPointerInfo().getLocation().getY()/2); // set mouse position to 0 for infinite movement
return deltaX; //return the overall change in position and add it to the rotation Y of our camera
} else { // return 0 if the lastMouse position is equal to the current mouse position, since there was no change in position
return 0;
}
} else { //return 0 since a frame was skipped
return 0;
}
}
Rather than resetting the position of the mouse yourself just call Mouse.setGrabbed(true) before you start using the mouse for this.

Getting jitters in my collision detection

So I'm doing a simple collision detection where the player is moved downward 3 every time it's updated and not on the ground, but when it is on the ground it moves the difference of it's position, and the grounds. But I'm getting jitters (It's moving down and up too much, and not being perfectly at a standstill).
My question is: How do I make this code calculate the difference properly?
Vector3f pos = new Vector3f(25,-50,25);
//Vector3f pos = new Vector3f(25,-50,25); isn't actually in the update method,
//but is in the object's constructer.
onGround = false;
Vector3f projPos = new Vector3f(pos);
projPos.y += fallSpeed;
//get a vector of all the triangles touching the player
Vector<Tri> tris = getTrisTouching(pos);
float minY;
//make it so if we don't have a list we don't get tossed into infinity
if(tris.size() > 0) minY = Float.POSITIVE_INFINITY;
else minY = 0;
for(int i = 0; i < tris.size(); i++){
Tri tri = tris.get(i);
if(projPos.y + radius <= tri.max.y){
float difference = tri.min.y - projPos.y;
if(difference < minY) minY = difference;
onGround = true;
}
}
if(onGround){
pos.y = minY;
}
else{
pos.y = projPos.y;
}
Your collision detection code (the 3 lines inside the first 'if' statement) is confusing but let's assume that when you're on the ground, the player doesn't touch any triangles (since it might be 1 pixel above them), so next frame you are moved down, then next frame you are moved back up.
A fix maybe would be to use projPos inside your for-loop instead of the actual position.

Categories