Image weirdness with slick2d graphics translation - java

I am making a game and I noticed whenever I use the graphics.translate function and after the translate this happens to the images.
Before Translation
After Translation
I was wondering if there is anyway to fix that or anyone else has the same issue. All these sprites are rendered from a spritesheet
EDIT: Translate code
public void translate(Graphics g, GameContainer container, int delta) {
g.translate(((container.getWidth() / 2) - this.x), ((container.getHeight() / 2) - this.y));
}
public void update(GameContainer container, int type){
if (type == 0) {
x = p.getX(); //p is the player
y = p.getY();
} else if (type == 1) {
x = player.x;
y = player.y;
}
if (offset) {
if (this.x - container.getWidth() / 2 < offsetMin[0]) {
x = offsetMin[0] + container.getWidth() / 2;
} else if (this.x + container.getWidth() / 2 > offsetMax[0]) {
x = offsetMax[0] - container.getWidth() / 2;
}
if (this.y - container.getHeight() / 2 < offsetMin[1]) {
y = offsetMin[1] + container.getHeight() / 2;
} else if (this.y + container.getHeight() > offsetMax[1]) {
y = offsetMax[1] - container.getHeight() / 2;
}
}
}

Try casting the x and y parameters for g.translate() to ints. That would eliminate any rounding errors where tiles don't end up on perfect pixel coords (IE 4, not 4.2).
Moved answer from comments to answer so it can be marked as accepted by OP

Related

Glitching when running program in parallel

I have a problem in regards to parallelism in javafx. More specifically, dividing the canvas of my program to run with multiple threads. When compiled, the program glitches out and doesn't work as supposed to. The code in the thread class is supposed to print out the Mandelbrot set, and the code in the application class is dividing the canvas into different parts that each should run in parallel. Here is the code:
public void MandelbrotSet(int n) {
int widthh = (int)canvas.getWidth();
int portion = widthh / n;
for (int i = 0; i < n; i++) {
int startX = i * portion;
int endX = startX + portion;
myMandelbrotParallelTEST2 thread = new myMandelbrotParallelTEST2(startX, endX, image, width, height, maximumIterations, canvas, zoom, xPos, yPos, hue, brightness, saturation, R, G, B);
thread.start();
//would add thread.join() here with try and catch
}
canvas.getGraphicsContext2D().drawImage(image, 0, 0);
}
this is how the code in the Thread class looks:
#Override
public void run(){
double centerY = canvas.getWidth() / 2.0;
double centerX = canvas.getHeight() / 2.0;
for (int x = start; x < end; x++) {
for (int y = 0; y < canvas.getHeight(); y++) {
double cr = xPos / width + (x - centerY) / zoom;
double ci = yPos / height + (y - centerX) / zoom; //getting position of the points on the canvas
int iterationsOfZ = 0;
double zr = 0.0;
double zi = 0.0;
while (iterationsOfZ < maximumIterations && (zr * zr) + (zi * zi) < 4) {
double oldZr = zr;
zr = (zr * zr) - (zi * zi) + cr;
zi = 2 * (oldZr * zi) + ci;
iterationsOfZ++;
}
int iterations = iterationsOfZ;
if (iterations == maximumIterations) { //inside the set
imagee.getPixelWriter().setColor(x, y, Color.rgb(R, G, B));
} else if (brightness == 0.9) { //white background
imagee.getPixelWriter().setColor(x, y, Color.hsb(hue, iterations / maximumIterations, brightness));
} else if (hue == 300) { //colorful background
imagee.getPixelWriter().setColor(x, y, Color.hsb(hue * iterations / maximumIterations, saturation, brightness));
} else if (hue == 0 && saturation == 0 && brightness == 1) {
imagee.getPixelWriter().setColor(x, y, Color.hsb(hue, saturation, brightness));
} else { //black background
imagee.getPixelWriter().setColor(x, y, Color.hsb(hue, saturation, iterations / brightness));
}
}
}
//canvas.getGraphicsContext2D().drawImage(imagee, 0, 0);
}
[this is how the program looks, and while panning around it glitches even more, but the execution time is really fast, which means that it is ran concurrently.]enter code here(https://i.stack.imgur.com/IZUfY.png)
I found that adding thread.join() fixes the problem, but then the program is ran on a single thread. Could anyone help me out resolve this issue?
What you are trying to do cannot be done with a Canvas because of the fx application thread restiction which has already been mentioned.
But it can be done via the WritableImage of JavaFX 13+ with support for Buffers. Writing into the buffer is not restricted in the above way and can thus be done in parallel with high performance.
I have compiled some examples (not any parallel ones) of how to use WritableImages with Buffers here: https://github.com/mipastgt/JFXToolsAndDemos

Java libgdx: limiting circular velocity (swinging entity)

I am currently working on a 2D side scroller and have implemented the techniques use in this article for a grapple hook, and it works really well. My problem is I want my player to be able to swing around the rope a little bit to gain a bit of momentum, but currently I can't stop the player from moving all the way up to 90 degrees either side. What techniques can be applied to force this limit?
I have tried using a separate player speed for swinging but this only slows the process down I can still swing up to 90 deg each side.
Here's my update function in the player
public void update(float dt){
//handle friction and air resistance
if(dx !=0){
if(touchingGround) {
// apply friction
if (dx > 0) {
dx -= retardation;
} else {
dx += retardation;
}
} else {
//applied air resistance
if (dx > 0) {
dx -= airResistance;
} else {
dx += airResistance;
}
}
}
// handle gravity
dy -= Constants.GRAVITY * dt;
if(dy < -terminalVelocity){
dy = -terminalVelocity;
}
/*
Handle Player movement
*/
if(right){
if(dx <= maxSpeed){
dx += acceleration;
}
dx = maxSpeed;
}
if(left){
if(dx <= -maxSpeed){
dx -= acceleration;
}
dx = -maxSpeed;
}
if(isGrappling){
//If we collide with something we need to stop grappling
if(hasCollided){
isGrappling = false;
} else {
// This algorithm from here:
// http://gamedev.stackexchange.com/questions/61596/player-rope-swing
float currentD = (float) Math.sqrt(((grappleX - x) * (grappleX - x)) + ((grappleY - y) * (grappleY - y)));
float prevX = getX(), prevY = getY();
if (currentD > grappleRadius) {
Vector2 hookPos = new Vector2(grappleX, grappleY);
Vector2 testPos = (new Vector2(x, y).sub(hookPos)).nor();
y = (hookPos.y + testPos.y * grappleRadius);
x = (hookPos.x + testPos.x * grappleRadius);
// s = d / t
dx += (x - prevX) / dt;
dy += (y - prevY) / dt;
}
}
}
/*
Collision Detection, handle last always!
*/
float oldX = getX(), oldY = getY();
boolean collisionX = false, collisionY = false;
// move on x
x += dx * dt;
// calculate the increment for step in #collidesLeft() and #collidesRight()
increment = collisionLayer.getTileWidth();
increment = getWidth() < increment ? getWidth() / 2 : increment / 2;
if(dx < 0) // going left
collisionX = collidesLeft();
else if(dx > 0) // going right
collisionX = collidesRight();
// react to x collision
if(collisionX) {
setX(oldX);
dx = 0;
}
// move on y
y += dy * dt;
// calculate the increment for step in #collidesBottom() and #collidesTop()
increment = collisionLayer.getTileHeight();
increment = getHeight() < increment ? getHeight() / 2 : increment / 2;
if(dy < 0) {
touchingGround = collisionY = collidesBottom();
// we can only jump 2 times before we have to touch the floor again
if(collisionY){
numberOfJumps = 2;
}
} else if(dy > 0) {
collisionY = collidesTop();
}
// react to y collision
if(collisionY) {
setY(oldY);
dy = 0;
}
hasCollided = collisionX || collisionY;
}
As I am not using any physics engine I chose to just emulate the physics by limiting the angle at which the player can apply force to the swing.
// check if angle permits movement
if(grappleAngle < Math.PI/9 && grappleAngle > -Math.PI/9) {
// handle momentum gaining on rope
if (right) {
dx += swingAcceleration * dt;
}
if (left) {
dx -= swingAcceleration * dt;
}
}

bilinear interpolation using java

I am trying to zoom an image twice using bilinear interpolation, but it's not working.It is giving errors like division by 0 , out of range value(the output color has exceeded 255). Here is my code :
int red1,green1,blue1;
int red2,green2,blue2;
int red3,green3,blue3;
int red4,green4,blue4;
int redf,greenf,bluef;
int x1,y1,x2,y2,x,y;
int a,b,c,d;
int var[][]=new int[4][4];
int inv[][]=new int[4][4];
//int cons[][]=new int[1][4];
//int col[][]=new int[1][4];
for(int i=0;i<height*2;i++)
{
//l=0;
for(int j=0;j<width*2;j++)
{
Color color=new Color(img.getRGB((int)(j/2),(int)(i/2)));
red=color.getRed();
green=color.getGreen();
blue=color.getBlue();
x=(int)(j/2);
y=(int)(i/2);
x1=(int)(j/2)+1;
y1=(int)(i/2)+1;
x2=(int)(j/2)-1;
y2=(int)(i/2)-1;
if(x1<0 || x1>=width || y1<0 || y1>=height)
{
//System.out.println("Yes");
red1=0;
green1=0;
blue1=0;
}
else
{
Color c1=new Color(img.getRGB(x1,y1));
red1=c1.getRed();
green1=c1.getGreen();
blue1=c1.getBlue();
}
if(x2<0 || x2>=width || y2<0 || y2>=height)
{
//System.out.println("Yes2");
red2=0;
green2=0;
blue2=0;
}
else
{
Color c2=new Color(img.getRGB(x2,y2));
red2=c2.getRed();
green2=c2.getGreen();
blue2=c2.getBlue();
}
if(x1<0 || x1>=width || y2<0 || y2>=height)
{
red3=0;
green3=0;
blue3=0;
}
else
{
Color c3=new Color(img.getRGB(x1,y2));
red3=c3.getRed();
green3=c3.getGreen();
blue3=c3.getBlue();
}
if(x2<0 || x2>=width || y1<0 || y1>=height)
{
red4=0;
green4=0;
blue4=0;
}
else
{
Color c4=new Color(img.getRGB(x2,y1));
red4=c4.getRed();
green4=c4.getGreen();
blue4=c4.getBlue();
}
if(x1<=0 || x1>width)
x1=0;
if(x2<=0 || x2>width)
x2=0;
if(y1<=0 || y1>height)
y1=0;
if(y2<=0 || y2>height)
y2=0;
var[0][0]=x1;
var[0][1]=y1;
var[0][2]=x1*y1;
var[0][3]=1;
var[1][0]=x2;
var[1][1]=y2;
var[1][2]=x2*y2;
var[1][3]=1;
var[2][0]=x1;
var[2][1]=y2;
var[2][2]=x1*y2;
var[2][3]=1;
var[3][0]=x2;
var[3][1]=y1;
var[3][2]=x2*y1;
var[3][3]=1;
inv=invert(var);
a=inv[0][0]*red1+inv[0][1]*red2+inv[0][2]*red3+inv[0][3]*red4;
b=inv[1][0]*red1+inv[1][1]*red2+inv[1][2]*red3+inv[1][3]*red4;
c=inv[2][0]*red1+inv[2][1]*red2+inv[2][2]*red3+inv[2][3]*red4;
d=inv[3][0]*red1+inv[3][1]*red2+inv[3][2]*red3+inv[3][3]*red4;
redf=a*x+b*y+c*x*y+d;
a=inv[0][0]*green1+inv[0][1]*green2+inv[0][2]*green3+inv[0][3]*green4;
b=inv[1][0]*green1+inv[1][1]*green2+inv[1][2]*green3+inv[1][3]*green4;
c=inv[2][0]*green1+inv[2][1]*green2+inv[2][2]*green3+inv[2][3]*green4;
d=inv[3][0]*green1+inv[3][1]*green2+inv[3][2]*green3+inv[3][3]*green4;
greenf=a*x+b*y+c*x*y+d;
a=inv[0][0]*blue1+inv[0][1]*blue2+inv[0][2]*blue3+inv[0][3]*blue4;
b=inv[1][0]*blue1+inv[1][1]*blue2+inv[1][2]*blue3+inv[1][3]*blue4;
c=inv[2][0]*blue1+inv[2][1]*blue2+inv[2][2]*blue3+inv[2][3]*blue4;
d=inv[3][0]*blue1+inv[3][1]*blue2+inv[3][2]*blue3+inv[3][3]*blue4;
bluef=a*x+b*y+c*x*y+d;
System.out.println(redf+" "+greenf+" "+bluef);//prints the value
Color nc=new Color(redf,greenf,bluef);
img1.setRGB(j, i, nc.getRGB());
}
}
Kindly help . I am trying to zoom by 2 , and using 4 neighbours(bilinear approach)
Sorry for being a bit late but for Bilinear Interpolation what you need to do is interpolation the results of two different interpolations. Basically it would look something like:
newX = x - 0.5
a1 = newX - (int) (newX)
newY = y - 0.5
a2 = newY - (int) (newY)
Red1 = getRed((int) (x - 0.5), (int) (y - 0.5))
Red2 = getRed((int) (x + 0.5), (int) (y - 0.5))
Red3 = getRed((int) (x - 0.5), (int) (y + 0.5))
Red4 = getRed((int) (x + 0.5), (int) (y + 0.5))
newRed = lerp(lerp(Red1, Red2, a1), lerp(Red3, Red4, a1), a2)
This could, of course be repeated for green and blue.
X and Y in this are source coords, so if you wanted to find the color at (3, 5) of your new image you would run this on (1.5, 2.5) aka your original coords divided by your scaling factor (2).
In case you don't know lerp() is generaly just
lerp(x, y, a)
return x * (1 - a) + y * a;
but if cycles really matter to you or you have a primitive FPU or any number of other special case the less precise
return a + f * (b - a);
can work.
*
Edit:
Since we're in java I've just used
(int)
to signify rounding down but it doesn't actually have to be an int there.

Issue comparing doubles

This simple if-comparison is not working, and i'm not sure why.
Code:
public abstract class Button extends Drawable_object {
...
#Override
public void update()
{
super.update();
mouseOver_last = mouseOver;
double mx = Game_logic.get_mouse_x();
double my = Game_logic.get_mouse_y();
//the not working statement check:
if ((mx <= x + ((double)width / 2))&&
(mx >= x - ((double)width / 2))&&
(my >= y - ((double)height / 2))&&
(my <= y + ((double)height / 2)))
{ mouseOver = true;}
else mouseOver = false;
....
}
Whilst Game_logic.get_mouse_x() and y are static methods:
public class Game_logic {
...
public static double get_mouse_x() { return mouse_x; }
public static double get_mouse_y() { return mouse_y; }
}
And those are set by Mouse adapaer in my main run class:
public Board() throws IOException, URISyntaxException {
...
private class MAdapter2 extends MouseAdapter {
#Override
public void mouseMoved(MouseEvent e) {
Game_logic.set_mouse_x(e.getX());
Game_logic.set_mouse_y(e.getY());
}
}
The thing is, when I draw on screen x - width / 2, mx and x + width / 2 (same with y), holding mouse at my desired position looks like statement must be true, but mouseOver is still false. How do i fix that?
This doesn't answer your question directly, I am just showing that it is possible for your if statement to come out true. I believe you should print out mx,my and compare them to what you expect their value should be. This may be where your problem lies. Obviously you should also check your choice of x,y,width,height.
public static void main(String[] args) {
boolean mouseOver;
int width = 50;
int height = 50;
double x = 40;
double y = 40;
double mx = 40;
double my = 40;
if ((mx <= x + ((double) width / 2)) && (mx >= x - ((double) width / 2))
&& (my >= y - ((double) height / 2))
&& (my <= y + ((double) height / 2))) {
mouseOver = true;
} else {
mouseOver = false;
}
System.out.println(mouseOver);
}
Please print out all values for mx,my,x,y,width,heigh and post them and compare to what you thought they would be.

Collision Detection on floor tiles Isometric game

I am writing a isometric tile based game where the characters can walk freely amongst the tiles, but not be able to cross over to certain tiles that have a collides flag. Sounds easy enough, just check ahead of where the player is going to move using a Screen Coordinates to Tile method and check the tiles array using our returned xy indexes to see if its collidable or not. if its not, then don't move the character. The problem I'm having is my Screen to Tile method isn't spitting out the proper X,Y tile indexes. This method works flawlessly for selecting tiles with the mouse. NOTE: My X tiles go from left to right, and my Y tiles go from up to down. Reversed from some examples on the net. Here's the relevant code:
public Vector2 ScreentoTile(Vector2 screenPoint) {
//Vector2 is just a object with x and y float properties
//camOffsetX,Y are my camera values that I use to shift everything but the
//current camera target when the target moves
//tilescale = 128, screenheight = 480, the -46 offset is to center
// vertically + 16 px for some extra gfx in my tile png
Vector2 tileIndex = new Vector2(-1,-1);
screenPoint.x -= camOffsetX;
screenPoint.y = screenHeight - screenPoint.y - camOffsetY - 46;
tileIndex.x = (screenPoint.x / tileScale) + (screenPoint.y / (tileScale / 2));
tileIndex.y = (screenPoint.x / tileScale) - (screenPoint.y / (tileScale / 2));
return tileIndex;
}
The method that calls this code is:
private void checkTileTouched () {
if (Gdx.input.justTouched()) {
if (last.x >= 0 && last.x < levelWidth && last.y >= 0 && last.y < levelHeight) {
if (lastSelectedTile != null) lastSelectedTile.setColor(1, 1, 1, 1);
Sprite sprite = levelTiles[(int) last.x][(int) last.y].sprite;
sprite.setColor(0, 0.3f, 0, 1);
lastSelectedTile = sprite;
}
}
if (touchDown) {
float moveX=0,moveY=0;
Vector2 pos = new Vector2();
if (player.direction == direction_left) {
moveX = -(player.moveSpeed);
moveY = -(player.moveSpeed / 2);
Gdx.app.log("Movement", String.valueOf("left"));
} else if (player.direction == direction_upleft) {
moveX = -(player.moveSpeed);
moveY = 0;
Gdx.app.log("Movement", String.valueOf("upleft"));
} else if (player.direction == direction_up) {
moveX = -(player.moveSpeed);
moveY = player.moveSpeed / 2;
Gdx.app.log("Movement", String.valueOf("up"));
} else if (player.direction == direction_upright) {
moveX = 0;
moveY = player.moveSpeed;
Gdx.app.log("Movement", String.valueOf("upright"));
} else if (player.direction == direction_right) {
moveX = player.moveSpeed;
moveY = player.moveSpeed / 2;
Gdx.app.log("Movement", String.valueOf("right"));
} else if (player.direction == direction_downright) {
moveX = player.moveSpeed;
moveY = 0;
Gdx.app.log("Movement", String.valueOf("downright"));
} else if (player.direction == direction_down) {
moveX = player.moveSpeed;
moveY = -(player.moveSpeed / 2);
Gdx.app.log("Movement", String.valueOf("down"));
} else if (player.direction == direction_downleft) {
moveX = 0;
moveY = -(player.moveSpeed);
Gdx.app.log("Movement", String.valueOf("downleft"));
}
//Player.moveSpeed is 1
//tileObjects.x is drawn in the center of the screen (400px,240px)
// the sprite width is 64, height is 128
testX = moveX * 10;
testY = moveY * 10;
testX += tileObjects.get(player.zIndex).x + tileObjects.get(player.zIndex).sprite.getWidth() / 2;
testY += tileObjects.get(player.zIndex).y + tileObjects.get(player.zIndex).sprite.getHeight() / 2;
moveX += tileObjects.get(player.zIndex).x + tileObjects.get(player.zIndex).sprite.getWidth() / 2;
moveY += tileObjects.get(player.zIndex).y + tileObjects.get(player.zIndex).sprite.getHeight() / 2;
pos = ScreentoTile(new Vector2(moveX,moveY));
Vector2 pos2 = ScreentoTile(new Vector2(testX,testY));
if (!levelTiles[(int) pos2.x][(int) pos2.y].collides) {
Vector2 newPlayerPos = ScreentoTile(new Vector2(moveX,moveY));
CenterOnCoord(moveX,moveY);
player.tileX = (int)newPlayerPos.x;
player.tileY = (int)newPlayerPos.y;
}
}
}
When the player is moving to the left (downleft-ish from the viewers point of view),
my Pos2 X values decrease as expected but pos2 isnt checking ahead on the x tiles, it is checking
ahead on the Y tiles(as if we were moving DOWN, not left), and vice versa, if the player moves down, it will check ahead on the X values (as if we are moving LEFT, instead of DOWN).
instead of the Y values.

Categories