javaswingdoublesetvaluejscrollbar

Java JScrollBar set value with double


So I am making a simple game in Java where there is a small tank in a tilemap. Though I have come across a problem concerning the JScrollBars: when I rotate the tank's body to a certain degrees east of north (specfically 14 or less) and I move the tank forwards (with the "W" key), the tank does not move in both the x and y directions as intended, only in the y direction. Here are pictures to help see what I mean:

Picture of tank rotated at 14 degrees east of north not translated upwards:

https://i.sstatic.net/7oexE.png

Picture of tank rotated at 14 degrees east of north translated upwards:

https://i.sstatic.net/Q1oTz.png

Clarification: when I rotate the tank's body with keys "A" and "D", there will be no x or y translations. When I press either the "W" or "S" key, which moves the tank forward or backwards (the direction in which it moves forwards or backwards is dependent on the angle at which the tank's body is at), then there will be x and y translations

This occurs because the value at which I am moving in the x direction is too small of a double value, and when casted to an int turns into 0 thus resulting in no x change. (I have to cast to an int because the JScrollBar.setValue() only accepts integers). Here is my code that explains the situation better:

int bodyAngle = 0; //the angle of the tank's body (it will face north as inital direction)
int d_angle = 2; //the change in angle when I click the rotate (see below)

//when I press the "D" key, the tank's body will rotate to the right by d_angle (and will keep rotating until I release "D")
case KeyEvent.VK_D:
    bodyAngle += D_ANGLE;
    ROTATE_TANK_BODY = ImageTool.rotateImage(TANK_BODY, bodyAngle, "body", 0);
    break;

//When the tank's angle is rotated and I press the forward key ("W"), there needs to be some math to calculate the correct x and y translations
case KeyEvent.VK_W:
    moveX = (int) Math.round(Math.sin(Math.toRadians(bodyAngle)));
    moveY = (int) Math.round(Math.cos(Math.toRadians(bodyAngle)));
    vScrollBar.setValue(vScrollBar.getValue() - moveY); //set new scrollbar values
    hScrollBar.setValue(hScrollBar.getValue() + moveX);
    break;

My question is, how can I increase the accuracy of the scrollbar's change in position? The loss of accuracy obviously comes from casting my predicted x translation to an integer, but I am not quite sure how to fix it.


Solution

  • You should proberbly be working directly with graphics and translating images rather than trying to use scroll bars, however, the issue is that the scroll bars typically have a range of 0-100. If you want greater precision of the scroll bar then simply change the range, but be warned though that for small/fine adjustments they physically cannot be shown/rendered on the screen because there is a limited number of pixels so it may appear as if nothing has changed until the scroll bar has moved far enough so that the image shifts over by a pixel.

    Example of increasing the scroll precision:

    //If you created the scroll bars yourself then you can set the range as follows:
    javax.swing.JScrollBar myBar = new JScrollBar(HORIZONTAL, startValue, extent, minValue, maxValue);
    
    //Or to edit a scroll bars inside an existing jScrollPane then you can change the max value:
    yourScrollPane.getHorizontalScrollBar().setMaximum(maxValue);
    

    If you want precision to half a decimal then the scroll bar range needs to be twice the size of your map/image. If you want presion to 1 decimal place then you scroll bar range needs to be 10 times the size of your map:

    //Map size in pixels, for example 400x400
    int mapSize = 400;
    //Scale factor of 10 for 0.1 decimal place precision, or scale factor of 2 for 0.5 precision
    int scaleFactor = 10;
    //Scroll bars with 1 decimal place precision (400 x 10 = 4000)
    vScrollBar.setMaximum(mapSize * scaleFactor);
    hScrollBar.setMaximum(mapSize * scaleFactor);
    
    //Then to scroll to 200.1,200.5 you can use (Note everything has a scale of 10 so 200 needs to be 2000)
    vScrollBar.setValue((int)200.1 * scaleFactor);
    hScrollBar.setValue((int)200.5 * scaleFactor);
    

    Again, I don't recommend this solution, and it likely will not change anything because small increments will not be shown on screen or it may appear stuttery.