Program is not checking the second condition - java

When I run my game it works fine on the bottom portion of the object collision but, it will not distguish that one and the other if. It is not reading the second one. I took a picture and you can see the (x, y) coords and it meets the condition but, I can still move.
IMG: http://i.stack.imgur.com/PjcHB.png
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
import javax.swing.ImageIcon;
public class Player{
int x = 1; // Location of player
int y = 314; // location of player
int xa = 0; // Representation of where the player goes
int ya = 0; // Representation of where the player goes
int playerWeight = 115;
private int speed = 2;
int[] playerPos = {x, y};
private static final int WIDTH = 30;
private static final int HEIGHT = 30;
private Game game;
public Player(Game game){
this.game=game;
}
public void move(){
System.out.println(x + ", " + y);
x = x + xa;
y = y + ya;
if(x + xa < 0) // Left Bounds
xa = 0;
if (x + xa > game.getWidth() - WIDTH) // Right Bounds
xa = 0;
if (y + ya < 0) // Top Bounds
ya = 0;
if(y + ya > game.getHeight() - WIDTH)
ya = 0;
if (collision()) // Tile bounds
y = y - 4;
if (collision2()){
if(x > 370 && x < 531 && y < 286){ // Check for 3 values
y = y + 4;
System.out.println("-x");
/*
* Use the gravity() method to determine player fall rate
*/
}
else if(x > 370 && x < 531 && y > 223){ // Check for 3 values
ya = 0;
System.out.println("+x");
/*
* Use the gravity() method to determine player fall rate
*/
}
}
}
// Method to find where player is located
public int[] Playerposition(){
x = 1;
y = 300;
return playerPos;
}
public void Gravity(){
}
public void paint(Graphics2D g2d){
//Draws player to screen
g2d.drawImage(getPlayerImg(), x, y, null);
}
public Image getPlayerImg(){
ImageIcon ic = new ImageIcon("C:/Users/AncientPandas/Desktop/KingsQuest/Misc/Images/Sprites/player.png");
return ic.getImage();
}
public void keyReleased(KeyEvent e){
xa = 0;
ya = 0;
}
public void keyPressed(KeyEvent e){
if (e.getKeyCode() == KeyEvent.VK_S)
xa = -speed;
if (e.getKeyCode() == KeyEvent.VK_F)
xa = speed;
if (e.getKeyCode() == KeyEvent.VK_E)
ya = -speed;
if (e.getKeyCode() == KeyEvent.VK_D)
ya = speed;
}
public Rectangle getBoundsPlayer(){
return new Rectangle(x, y, WIDTH, HEIGHT);
}
private boolean collision(){
return game.maplayout.getBoundsBlock().intersects(getBoundsPlayer());
}
private boolean collision2(){
return game.maplayout.getBoundsBlock2().intersects(getBoundsPlayer());
}
}

Change:
else if(x > 370 && x < 531 && y > 223){ // Check for 3 values
ya = 0;
System.out.println("+x");
/*
* Use the gravity() method to determine player fall rate
*/
}
to:
if(x > 370 && x < 531 && y < 286){ // Check for 3 values
y = y + 4;
System.out.println("-x");
/*
* Use the gravity() method to determine player fall rate
*/
}
if(x > 370 && x < 531 && y > 223){ // Check for 3 values
ya = 0;
System.out.println("+x");
/*
* Use the gravity() method to determine player fall rate
*/
}
Reason being is that the keyword "else" will only execute code within it's block if the above "if" statement's condition fails/requirements are not met. For example:
boolean anInteger = 9;
if (anInteger == 1999) {
// ...
} else {
// If 'anInteger' is not equal to 9, then execute the following code (within this block)
// ...
}

Related

How to constrain sprite movement within isometric boundaries in libgdx?

I am currently generating an isometric map which should allow some sprites to move randomly within its bounds. My sprites, or 'humans' do move within a specified constraint however it is not the correct boundaries I wish to set it to. Below is my code.
public class Human implements Entity {
private int[][] map;
public static final int TILE_WIDTH = 34;
public static final int TILE_HEIGHT = 34;
private int min = 100;
private int max = 200;
private Texture img;
// position variable
private Vector2 pos;
private float time;
public Human() {
img = new Texture(Gdx.files.internal("humanFF.png"));
// coordinates of human initial position
pos = new Vector2(9, 220);
// for locking movement if need be.
time = 2;
map = randomGenerator();
}
#Override
public void render(SpriteBatch batch) {
batch.draw(img, pos.x, pos.y);
}
#Override
public void update(float delta) {
time += delta;
Random rand = new Random();
int upperbound = 2;
double double_random = rand.nextDouble(upperbound);
// lock human, can only move once every 2 secs.
if (time > 0) {
move();
time = 0;
}
}
private void move() {
/** Calculation **/
for (int row = map.length - 1; row >= 0; row--) {
for (int col = map.length - 1; col >= 0; col--) {
float x = (col - row) * (TILE_WIDTH / 2f - 2);
float y = (col + row) * (TILE_HEIGHT / 4f);
}
}
// after calculation, mapWidth is 525 pixels.
int mapWidth = map.length * (TILE_WIDTH / 2 - 2);
// after calculation, mapHeight is 280 pixels.
int mapHeight = map.length * (TILE_HEIGHT / 4);
// Calculate the minimum and maximum x-coordinates.
float minX = 0;
float maxX = mapWidth - TILE_WIDTH;
if (maxX < 0) {
maxX = 0;
}
// max-x coordinate is 491.0. min-x coordinate is 0.0.
// Calculate the minimum and maximum y-coordinates.
float minY = 0;
float maxY = mapHeight - TILE_HEIGHT;
if (maxY < 0) {
maxY = 0;
}
// check the position of human against map boundaries
if (pos.x < minX) {
pos.x = minX;
} else if (pos.x > maxX) {
pos.x = maxX;
}
if (pos.y < minY) {
pos.y = minY;
} else if (pos.y > maxY) {
pos.y = maxY;
}
// min-y coordinate is 0.0, max-y coordinate is 246.0.
// a variable to store a random generated value between 100 and 200.
int a = (int) (Math.random() * (max - min + 1) + min);
float newX = pos.x;
float newY = pos.y;
// move up
if (a <= 125) {
newX -= 15;
newY += 8.5;
}
// move down
else if (a <= 150 && a > 125) {
newX += 15;
newY -= 8.5;
}
// move left
else if (a <= 175 && a > 150) {
newX -= 15;
newY -= 8.5;
}
// move right
else if (a <= 200 && a > 175) {
newX += 15;
newY += 8.5;
}
if (newX >= minX && newX <= maxX && newY >= minY && newY <= maxY) {
pos.x = newX;
pos.y = newY;
}
}
public int[][] randomGenerator() {
Random r = new Random();
int Size = r.nextInt(35, 36);
int[][] map = new int[Size][Size];
for(int row = 0; row < map.length; row++) {
for(int col = 0; col < map.length; col++) {
int Number = r.nextInt(10);
if(Number == 0) {
map[row][col] = 0;
} else if (Number == 1) {
map[row][col] = 1;
}
else if (Number == 2) {
map[row][col] = 2;
}
else if (Number == 3) {
map[row][col] = 3;
}
else if (Number == 4) {
map[row][col] = 4;
}
else if (Number == 5) {
map[row][col] = 5;
}
else if (Number < 8) {
map[row][col] = 6;
}
else {
map[row][col] = 7;
}
}
}
map[0][0] = 1;
return map;
}
}
Based on the above, I am generating a random value which defines the movement of my 'humans' thus adding or subtracting from their x and y positions. In my attempt to tackle the problem of these sprites moving outside of my isometric map, I tried to calculate my mapWidth, mapHeight, min-x, max-x, min-y and max-x and then checking the position of my human against these boundaries to determine their movement.
Although these sprites now move within a constraint, it is not same dimension as my isometric map, but are now constrained to a rectangular-shaped boundary. How do I modify my code so that the sprites only move within the isometric map I have generated?
Below is a photo for visualisation.
The coordinate system you use for Human enties is ordinary orthogonal, you don't map these coordinates to an isometric view but you -have to- map them onto the isometric background. Screen coordinate system is basically different from the isometric one. When you render you need to map coordinates so that
(0,0)-> left corner
(0,maxY)->top corner
(maxX,maxY)->right corner
(maxX,0)->bottom corner
See here for to and back(map screen touch events to the map etc) conversion LibGdx render a sprite on top of a isometric tile

Transition 2D player Position A to B on JAVA

Am having issues trying to figure out how to translate or 'animate' my player's position to a new tile, this is what am doing :
if (input.right){
x += 1;
Right now am listening for key.inputs and then x++/x-- or y++/y-- on my players position that makes him move pixel by pixel, but i want my player to move exactly to the next tile(32 pixels) with one hit of the key with like a linear transition from the player's tile position to the next tile over time?
Something like (pseudo code i think..)
if input && walking false
walking = true
increment 1 by 1 32 ints to X over time?
after completed walking = false
I still cant even figure out the logic behind something like that.
An example is the movement in a game called Tibia.
Now Some bits of my code (player related)..
GAMECLASS >
public Game()
player = new Player(playerSpawn.x(), playerSpawn.y(), key);
player.init(level);
public void run()
....
render();
frames++;
....
public void update()
key.update();
player.update();
level.update();
public void render()
.....
int xScroll = ( player.x + 32) - screen.width / 2;
int yScroll = ( player.y + 32) - screen.height / 2;
level.render(xScroll, yScroll, screen);
player.render(screen);
for (int i =0; i < pixels.length; i++){
pixels[i] = screen.pixels[i];
}
SCREENCLASS >
......
public int[] pixels;
public int[] tiles = new int[VIEW_SIZE * VIEW_SIZE];
.....
public void renderTile(int xp, int yp, Tile tile){
xp -= xOffset;
yp -= yOffset;
for (int y = 0; y < tile.sprite.SIZE; y++){
int ya = y + yp;
for (int x = 0; x < tile.sprite.SIZE; x++){
int xa = x + xp;
if (xa < -tile.sprite.SIZE || xa >= width || ya < 0 || ya >= height) break;
if (xa < 0) xa = 0;
pixels[xa + ya * width] = tile.sprite.pixels[x + y * tile.sprite.SIZE];
}
}
}
//THIS IS THE METHOD CALLED TO RENDER THE PLAYER > SEE BELLOW AT THE PLAYER CLASS FOR THE CALL
public void renderMob(int xp, int yp, Mob mob){
xp -= xOffset;
yp -= yOffset;
for (int y = 0; y < 64; y++){
int ya = y + yp;
int ys = y;
for (int x = 0; x < 64; x++){
int xa = x + xp;
int xs = x;
if (xa < -64 || xa >= width || ya < 0 || ya >= height) break;
if (xa < 0) xa = 0;
int col = mob.getSprite().pixels[xs + ys * 64];
if (mob instanceof Chazer && col == 0xFF9b0000) col = 0xff54ff00;
if (col != 0xFFFF00FF) pixels[xa + ya * width] = col;
}
}
}
PLAYERCLASS >
public Player(int x , int y, Keyboard input){
this.x = x;
this.y = y;
this.input = input;
}
//PLAYER UPDATE
public void update(){
if (anim < 7500) anim++;
else anim = 0;
if (input.down) ya = 1;
if (input.up) ya = -1;
if (input.left) xa = -1;
if (input.right) xa = 1;
//CHECK BELLOW TO THIS MOVE METHOD
if (xa != 0){
move(xa, 0);
} else if(ya != 0){
move(0, ya);
}
}
clear();
}
//HERE ANIMATION AND CHOOSE WHAT SPRITE = WHERE PLAYER IS LOOKING AT
public void render(Screen screen){
if (dir == 0) {
sprite = Sprite.player_n;
if (walking) {
if (anim % 20 > 10){
sprite = sprite.player_n1;
} else {
sprite = sprite.player_n2;
}
}
}
if (dir == 1) {
sprite = Sprite.player_e;
if (walking) {
if (anim % 20 > 10){
sprite = sprite.player_e1;
} else {
sprite = sprite.player_e2;
}
}
}
if (dir == 2) {
sprite = Sprite.player_s;
if (walking) {
if (anim % 20 > 10){
sprite = sprite.player_s1;
} else {
sprite = sprite.player_s2;
}
}
}
if (dir == 3) {
sprite = Sprite.player_w;
if (walking) {
if (anim % 20 > 10){
sprite = sprite.player_w1;
} else {
sprite = sprite.player_w2;
}
}
}
// ADDING OFFSET CUZ THE PLAYER IS DOUBLE THE SIZE OF THE TILE
int xx = x - 42;
int yy = y - 42;
screen.renderMob(xx, yy, sprite);
}
//THIS IS HOW I MOVE THE PLAYER
public void move(int xa, int ya){
if (xa != 0 && ya != 0){
move(xa, 0);
move(0, ya);
return;
}
if (xa > 0) dir = 1;
if (xa < 0) dir = 3;
if (ya > 0) dir = 2;
if (ya < 0) dir = 0;
if(!collision(xa, 0)){
x += xa;
}
if(!collision(0, ya)){
y += ya;
}
}
Thanks alooot!
**Run method!
public void run() {
long xlastTime = System.nanoTime();
long timer = System.currentTimeMillis();
final double xns = 1000000000.0 / 60.0;
double delta = 0;
int frames = 0;
requestFocus();
while(running){
long xnow = System.nanoTime();
delta += (xnow-xlastTime) / xns;
xlastTime = xnow;
while (delta >= 1) {
update();
delta--;
}
render();
frames++;
if (System.currentTimeMillis() - timer > 1000){
timer += 1000;
frame.setTitle(title + " | " + frames + " fps");
frames = 0;
}
}
stop();
}
What I would do is declare two int fields in the player class:
private float xToMove = 0;
private float yToMove = 0;
Then, under your input event:
if (input.down && yToMove == 0)
yToMove = -32;
if (input.up && yToMove == 0)
yToMove = 32;
if (input.left && xToMove == 0)
xToMove = -32;
if (input.right && xToMove == 0)
xToMove = 32;
And finally, in your Player class's update method:
public void update()
{
if (xToMove > 0)
{
xToMove--;
x++;
}
if (xToMove < 0)
{
xToMove++;
x--;
}
if (yToMove > 0)
{
yToMove--;
y++;
}
if (yToMove < 0)
{
yToMove++;
y--;
}
}
Of course this is simplified a bit but the concept is there
EDIT: to change the speed. Note that xToMove and yToMove have been changed to floats.
You can use a float to represent the amount of time 1 move takes
float period = 1000; //The time one move takes in milliseconds
Somewhere you should calculate the number of pixels to be moved each frame. You could make a calculateSpeed() method or just throw it into the constructor or something. Depends on if you want speed to change during the game.
float speed = 32f / (fps * (period / 1000f)); //fps should be obtained dynamically and should be a float
Then when you update you should do this:
if (xToMove > 0)
{
xToMove -= speed;
x += speed;
if (xToMove <= 0)
{
//Set these guys to nice even numbers to prevent problems
xToMove = 0;
x = (float) Math.round(x);
}
}
Also make sure that x and y are floats.
EDIT 2: fps
int frames = 0;
int fps = 60;
requestFocus();
while(running){
long xnow = System.nanoTime();
delta += (xnow-xlastTime) / xns;
xlastTime = xnow;
while (delta >= 1) {
update();
delta--;
}
render();
frames++;
if (System.currentTimeMillis() - timer > 1000){
timer += 1000;
fps = frames;
frame.setTitle(title + " | " + fps + " fps");
frames = 0;
}
}
stop();

Finding cause of jitter in collision detection

I'm looking for help in finding the source of jitter when using collision detection.
I've implemented a java game (using eclipse and slick2d) and have been loosely following this guide:
http://katyscode.wordpress.com/2013/01/18/2d-platform-games-collision-detection-for-dummies
but of course changing bits where necessary to suit my game and java not cpp.
From the research I have done I think the root cause of my jitter is coming from rounding errors.
Despite that being my main suspect, I still haven't been able to identify where it's occurring.
Sorry if the indentation isn't quite right there, had a little trouble using the code block recognition.
Basically I'm creating variables in the class.
In init() I set up most of the resources.
In render() all the drawing takes place. Note the graphics translation so the camera follows the player.
In update I'm of course updating the position of the player according to user input, gravity and friction.
I also call my collision detection from this method.
Collision detection is working on a penetration resolution method.
(Yes I know I'm exhaustively comparing with every single world object. I will be improving my efficiency with AABB's when I have sorted more fundamental problems out. Like jitter!)
My method first calculates how much the player expects to move in each axis, then for each world object it checks for intersection with the players bounding points (floating point values that represent coordinates around the player). It checks this in each direction and uses the result to determine in which axis the collision occurred, if any, so that the appropriate action can be taken.
Sorry it's a put load of code, but it's collision detection after all, which isn't a small thing.
Here is my Play class where all the updating goes on for the game:
package GameFiles;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.newdawn.slick.*;
import org.newdawn.slick.state.*;
import java.awt.Rectangle;
//import java.awt.geom.Rectangle2D;
public class Play extends BasicGameState{
static int tileSize = 32;
File levelMap;
SpriteSheet spriteSheet;
int[][] currentMap;
Image[] groundTiles = new Image[4];
//List<Rectangle2D> levelBounds = new ArrayList<Rectangle2D>();
List<Rectangle> levelBounds = new ArrayList<Rectangle>();
Player player;
float playerX, playerY;
int dir;
float acc, mov, friction, gravity;
float runSpeed;
float maxAcc;
boolean inAir, jumping, keyDown;
boolean exitFlag;
int mapHeight, mapWidth;
float mapX, mapY;
float speedX, speedY;
int worldObjectCount;
int iterations;
public Play(int state){
}
public void init(GameContainer gc, StateBasedGame sbg) throws SlickException{
playerX = Game.scrWidth/2;
playerY = Game.scrHeight - tileSize - tileSize;
player = new Player(playerX, playerY);
levelMap = new File("maps/lvl1.txt");
spriteSheet = new SpriteSheet("res/tiles/tilesets/DungeonCrawlTilesetBW.png", tileSize, tileSize);
try
{
currentMap = readMap(levelMap);
}
catch (IOException e)
{
System.out.println("Array size mismatch when copying arrays.");
e.printStackTrace();
}
levelBounds.clear();
for(int x = 0; x < mapWidth; x++)
{
for(int y = 0; y < mapHeight; y++){
if(currentMap[x][y] == 1){
levelBounds.add(new Rectangle(x*tileSize, Game.scrHeight - mapHeight*tileSize + y*tileSize, tileSize, tileSize));
//levelBounds.add(new Rectangle2D.Float(x*tileSize, Game.scrHeight - mapHeight*tileSize + y*tileSize, tileSize, tileSize));
System.out.println("Added new bounding box: " + (x*tileSize) + ", " + (Game.scrHeight - mapHeight*tileSize + y*tileSize) + ", " + tileSize);
}
}
}
worldObjectCount = levelBounds.size();
System.out.println("World object count: " + worldObjectCount);
groundTiles[0] = spriteSheet.getSubImage(4, 16);
groundTiles[1] = spriteSheet.getSubImage(13, 19);
dir = 1;
acc = 0.0f;
mov = 0.0f;
friction = 4f;
gravity = 4f;
runSpeed = 0.6f;
maxAcc = -1f;
inAir = false;
jumping = false;
keyDown = false;
exitFlag = false;
speedX = 0.0f;
speedY = 0.0f;
iterations = 3;
}
public void render(GameContainer gc, StateBasedGame sbg, Graphics g) throws SlickException{
//determine cameraX and cameraY
float cameraX, cameraY;
cameraX = player.getX() - Game.scrWidth/2;
cameraY = player.getY() - (Game.scrHeight/2 - tileSize - tileSize);
g.translate(-cameraX, -cameraY);
player.render(g);
for(int x = 0; x < mapWidth; x++)
{
for(int y = 0; y < mapHeight; y++){
if(currentMap[x][y] == 1){
groundTiles[0].draw(x*tileSize, Game.scrHeight - mapHeight*tileSize + y*tileSize);
}
}
}
g.translate(cameraX, cameraY);
}
public void update(GameContainer gc, StateBasedGame sbg, int delta) throws SlickException{
Input input = gc.getInput();
float secondsElapsed = delta/1000.0f;
checkCollisions(secondsElapsed);
player.setX((player.getX() + speedX));
player.setY((player.getY() - speedY));
//check inputs
checkKeyEvents(input);
//slow down / friction
if(!keyDown){
if(mov < 0)
mov += friction * secondsElapsed;
else
mov -= friction * secondsElapsed;
}
speedX = mov;
if (speedX > 0 && speedX < friction * secondsElapsed) speedX = 0;
if (speedX < 0 && speedX > -friction * secondsElapsed) speedX = 0;
//jump or fall
acc -= gravity * secondsElapsed;
if (acc < maxAcc){
acc = maxAcc;
}
speedY = acc;
//exit when exitFlag true
if(exitFlag){
gc.exit();
}
}
public void checkCollisions(float secondsElapsed){
boolean contactX = true, contactYbottom = true, contactYtop = true;
// Keep iterating the contact solver until the maximum number of iterations is reached
// or no collisions are detected
for (int iteration = 0; iteration < iterations && (contactX || contactYbottom || contactYtop); iteration++)
{
float nextMoveX = speedX * secondsElapsed;
float nextMoveY = speedY * secondsElapsed;
contactX = contactYbottom = contactYtop = false;
float projectedMoveX, projectedMoveY, originalMoveX, originalMoveY;
originalMoveX = nextMoveX;
originalMoveY = nextMoveY;
for (int o = 0; o < worldObjectCount && !contactX && !contactYbottom && !contactYtop; o++)
{
for (int dir = 0; dir < 6; dir++)
{
//top, bottom, left, left, right, right.
if (dir == 0 && nextMoveY < 0) continue;
if (dir == 1 && nextMoveY > 0) continue;
if (dir == 2 && nextMoveX > 0) continue;
if (dir == 3 && nextMoveX > 0) continue;
if (dir == 4 && nextMoveX < 0) continue;
if (dir == 5 && nextMoveX < 0) continue;
projectedMoveX = (dir >= 2? nextMoveX : 0);
projectedMoveY = (dir < 2? nextMoveY : 0);
float[][] collisionPoint = player.getBounds();
Rectangle curRect = new Rectangle(levelBounds.get(o).x, levelBounds.get(o).y, levelBounds.get(o).width, levelBounds.get(o).height);
//Rectangle2D curRect = levelBounds.get(o).getBounds2D();
while (curRect.contains(collisionPoint[dir][0] + projectedMoveX, collisionPoint[dir][1] + projectedMoveY)
|| curRect.intersects(collisionPoint[dir][0] + projectedMoveX, collisionPoint[dir][1] + projectedMoveY, 1, 1))
{
if (dir == 0) projectedMoveY += 0.05f; //top collision
if (dir == 1) projectedMoveY -= 0.05f; //bottom collision
if (dir == 2) projectedMoveX += 0.05f; //left collision
if (dir == 3) projectedMoveX += 0.05f;
if (dir == 4) projectedMoveX -= 0.05f; //right collision
if (dir == 5) projectedMoveX -= 0.05f;
}
if (dir >= 2 && dir <= 5)
nextMoveX = projectedMoveX;
if (dir >= 0 && dir <= 1)
nextMoveY = projectedMoveY;
}
if (nextMoveY > originalMoveY && originalMoveY != 0)
{
contactYtop = true;
}
if (nextMoveY < originalMoveY && originalMoveY != 0)
{
contactYbottom = true;
}
if (Math.abs(nextMoveX - originalMoveX) > 0.01f)
{
contactX = true;
}
if (contactX && contactYtop && speedY > 0)
speedY = nextMoveY = 0;
}
if (contactYbottom || contactYtop)
{
player.setY(player.getY() + nextMoveY);
speedY = 0;
acc = 0;
if (contactYbottom)
jumping = false;
}
if (contactX)
{
player.setX(player.getX() + nextMoveX);
speedX = 0;
mov = 0;
}
}//end collisions
}
public int[][] readMap(File level) throws IOException, SlickException{
BufferedReader br = new BufferedReader(new FileReader(level));
mapWidth = Integer.parseInt(br.readLine());
mapHeight = Integer.parseInt(br.readLine());
int[][] map = new int[mapWidth][mapHeight];
for(int row = 0; row < mapHeight; row++)
{
String line = br.readLine();
if(line == null || line.isEmpty())
{
System.out.println("Line is empty or null");
}
else
{
String[] tileValues = line.split(",");
for(int col = 0; col < mapWidth; col++)
{
map[col][row] = Integer.parseInt(tileValues[col]);
}
}
}
br.close();
return map;
}
public void checkKeyEvents(Input input){
//key input events
if(input.isKeyPressed(Input.KEY_DOWN)){
}
if(input.isKeyPressed(Input.KEY_UP)){
if(!jumping){
acc = 1f;
}
jumping = true;
}
if(input.isKeyDown(Input.KEY_LEFT) && !input.isKeyDown(Input.KEY_RIGHT)){
keyDown = false;
mov -= 0.006f;
if (mov < -runSpeed){
mov = -runSpeed;
}
}
if(input.isKeyDown(Input.KEY_RIGHT) && !input.isKeyDown(Input.KEY_LEFT)){
keyDown = false;
mov += 0.006f;
if (mov > runSpeed){
mov = runSpeed;
}
}
if(input.isKeyPressed(Input.KEY_ESCAPE)){
exitFlag = true;
}
}
public int getID(){
return 1;
}
}
Since I can't predict what more info a potential helper might need, I'll leave it at that for now, but of course I can provide any more info when/where needed.
Thanks,
J.

Move tile by tile with dynamic speed

I'm using java with slick2d library and trying to move tile by tile with dynamic speed. I have tried a couple methods but none of them can move with dynamic speed between the tiles. Can someone help me with that and give some examples?
edit:
this two methods have I tried
move with out delta
movementSpeed = 2;
//decide direction
if(targetX != x)
{
animation.update(delta);
if(originalX < targetX)
x += movementSpeed;
else if(originalX > targetX)
x -= movementSpeed;
}
if(targetY != y)
{
animation.update(delta);
if(originalY < targetY)
y += movementSpeed;
else if(originalY > targetY)
y -= movementSpeed;
}
lerp
public static float lerp(float start, float stop, float t)
{
if (t < 0)
return start;
return start + t * (stop - start);
}
public void move(long delta)
{
if (procentMoved == 0)
{
if (getSpeed(targetX, targetY) != 0)
{
movementSpeed = getSpeed(targetX, targetY);
} else
{
targetX = originalX;
targetY = originalY;
}
}
if (procentMoved < 1)
{
animation.update(delta);
// movementSpeed = getSpeed(targetX, targetY);
procentMoved += movementSpeed;
} else if (procentMoved > 1)
{
animation.update(delta);
//TODO fix bouncing bug
procentMoved = 1;
}
+ movementSpeed);
x = lerp(originalX, targetX, procentMoved);
y = lerp(originalY, targetY, procentMoved);
if (x == targetX)
;
originalY = x;
if (y == targetY)
;
originalY = y;
}
It seems as if this could be your issue. Your if statements are just closing and not really doing its part. Also, you're variables are mixed up as well.
if (x == targetX)
; // This will skip the If statement
originalY = x;
if (y == targetY)
; // This will skip the If statement
originalY = y;
}
In all reality you're saying
orginalY = x; // Y = X?
orginalY = y; // Y = Y
Please do not take this to heart. I'm still having this issue as well, however I'm having to do some corrections and auto placements in order for this to work correctly.

How can I simplify this code? (Chess game obstruction testing)

I'm making a chess game in Java, and testing to make sure there are no pieces blocking the path of the piece being moved. The piece moves from (srcX,srcY) to (dstX,dstY).
I've written this code which checks if there are any obstructions for a rook:
if(dstY == srcY) {
// No change on Y axis, so moving east or west
if(dstX > srcX) {
// Moving east
// Test every cell the piece will pass over
for(int x = srcX+1; x < dstX; x++) {
// Is the cell set?
if(isPiece(x, srcY)) {
return true;
}
}
} else {
// Must be moving west
// Test every cell the piece will pass over
for(int x = srcX-1; x > dstX; x--) {
// Is the cell set?
if(isPiece(x, srcY)) {
return true;
}
}
}
} else if(dstX == srcX) {
// No change on X axis, so moving north or south
if(dstY > srcY) {
// Moving north
// Test every cell the piece will pass over
for(int y = srcY+1; y < dstY; y++) {
// Is the cell set?
if(isPiece(srcX, y)) {
return true;
}
}
} else {
// Must be moving south
// Test every cell the piece will pass over
for(int y = srcY-1; y > dstY; y--) {
// Is the cell set?
if(isPiece(srcX, y)) {
return true;
}
}
}
}
but it's a bit big and I'm sure it can be simplied.. any ideas?
ps, this is ONLY obstruction testing. I've already validated everything else.
Once you've tested for direction, you can set dx, dy values (e.g. dx=1, dy=0 for east). Then you can have a single for loop for all cases and just increment x and y by dx and dy respectively at each iteration.
You can then simplify the direction checking into the following:
if dstY == srcY: dy = 0
else: dy = (dstY - srcY) / abs(dstY - srcY)
if dstX == srcX: dx = 0
else: dx = (dstX - srcX) / abs(dstX - srcX)
Code:
int dx, dy;
if (dstY == srcY) dy = 0;
else dy = (dstY - srcY) / Math.abs(dstY - srcY);
if (dstX == srcX) dx = 0;
else dx = (dstX - srcX) / Math.abs(dstX - srcX);
while (srcX != dstX || srcY != dstY) {
srcX += dx; srcY += dy;
if (isPiece(srcX, srcY))
return true;
}
return false;
Also beware that this code (and yours) will fail if the move is not horizontal, vertical or diagonal.
You could do something along these lines (untested as I don't have a compiler to hand):
int dx = 0;
int dy = 0;
if (dstX != srcX) {
dx = (dstX > srcX) ? 1 : -1;
} else if (dstY != srcY) {
dy = (dstY > srcY) ? 1 : -1;
}
int x = srcX + dx;
int y = srcY + dy;
while (x != dstX || y != dstY) {
if (isPiece(x, y)) return true;
x += dx;
y += dy;
}
First, write tests. Lots and lots of tests. That way you can be confident that you're simplifying without changing the meaning of the code.
Refactoring without unit tests is like walking a high wire without a safety net.
Nearly the same, but with for loops:
// move along x axis
for (int x = 1; x < Math.abs(srcX - dstX); x++) {
int curX = (srcX - dstX) < 0 ? srcX - x : srcX + x;
if (isPiece(curX, srcY))
return true;
}
// move along y axis
for (int y = 1; y <= Math.abs(srcY - dstY); y++) {
int curY = (srcY - dstY) < 0 ? srcY - y : srcY + y;
if (isPiece(srcX, curY))
return true;
}
My soultion would be: introduce a direction class, and then do the check in this style:
isBlocked(startPossition, direction, numberOfFields)
I have done a little example, using 3 Classes.
Direction - an enum to represent the 8 directions (2 horizontal, 2 vertical, 4 diagonal)
Position - the x and y value of an position
LinarMove - represent one linear Move(startPossition, direction, numberOfFields) and contains the isBlockedMethod
The Enum:
public enum Direction {
UP(0, 1),
DOWN(0, -1),
LEFT(1, 0),
RIGHT(-1, 0),
UP_LEFT(UP, LEFT),
UP_RIGTH(UP, RIGHT),
DOWN_LEFT(DOWN, LEFT),
DOWN_RIGHT(
DOWN, RIGHT);
private final int incrementX;
private final int incrementY;
private Direction(int incrementX, int incrementY) {
this.incrementX = incrementX;
this.incrementY = incrementY;
}
private Direction(Direction sub1, Direction sub2) {
this.incrementX = sub1.incrementX + sub2.incrementX;
this.incrementY = sub1.incrementY + sub2.incrementY;
}
public Position oneField(Position start) {
return new Position(start.getX() + this.incrementX, start.getY()
+ this.incrementY);
}
}
The purpuse of second constructor is only that it alowes to write the diagonal moves in a more readable way.
public class Position {
private final int x;
private final int y;
public Position(int x, int y) {
super();
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
#Override
public String toString() {
return "x:" + x + ", y:" + y;
}
}
The Move contains the isBlocked Method -- you can see how small it get, and how readable it become. At least there is no single direction related if statement left.
The name LinareMove sugget that there is possible an other kind of move for the knight.
public class LinearMove {
private final Position start;
private final Direction direction;
/** Length of the move. */
private final int numberOfFields;
public LinearMove(Position start, Direction direction, int numberOfFields) {
super();
this.start = start;
this.direction = direction;
this.numberOfFields = numberOfFields;
}
boolean isBlocked() {
Position pos = this.start;
for (int i = 0; i < (this.numberOfFields - 1); i++) {
pos = this.direction.oneField(pos);
if (isPiece(pos)) {
return true;
}
}
return false;
}
boolean isPiece(Position pos) {
//Dummy;
System.out.println(pos);
return false;
}
}
And this is how it works:
public static void main(String[] args) {
new LinearMove(new Position(1, 1), Direction.RIGHT, 3).isBlocked();
}
You maybe noticed, that the knights move is some kind of probem. With this soultion you could model it in two ways:
- 4 special Directions
- an other kind of move class (this is the more cleaner way, because you could always return true, in the isBockedMethod)

Categories

Resources