I am trying to make a game where enemies spawn from the top (like a vertical scrolling game) and one kind of enemy will basically follow the player's X coordinate while going down. The enemy class is called Follower and right now it does points to the player (see update function on Follower) but it's not as accurate as I need it to be. For example, if the player accelerates, the follower won't be able to see him all the time.
One way to look at it is that I want the position of the player to be a coordinate in a radiant system and make the vertices of my Follower accurately just rotate and create a straight line looking at it every frame
here is the Follower Class:
public class Follower {
Player target; //follow this
//position
private Vector2 position;
private float x;
private float y;
//speed
private Vector2 velocity;
private float speed;
private float radians;
private float faceTarget;
//dimensions
private float[] shapeX;
private float[] shapeY;
private int numPoints; //vertices for the shape
private boolean remove; //to remove from the game
public Follower(float x,float y, Player target){
this.target = target;
this.x = x;
this.y = y;
velocity = new Vector2(0, 0);
numPoints = 4;
speed = 200;
shapeX = new float[numPoints];
shapeY = new float[numPoints];
radians = 3.1415f / 2;
setShape();
}
public void setShape(){
//top vertice
shapeX[0] = x + MathUtils.cos(radians) * 30;
shapeY[0] = y + MathUtils.sin(radians) * 30;
//left vertice
shapeX[1] = x + MathUtils.cos(radians - 4 * 3.1415f / 10) * 30;
shapeY[1] = y + MathUtils.sin(radians - 4 * 3.1415f / 10) * 30;
//bottom vertice
shapeX[2] = x + MathUtils.cos(radians + 3.1415f) * 60;
shapeY[2] = y + MathUtils.sin(radians + 3.1415f) * 60;
//left vertice
shapeX[3] = x + MathUtils.cos(radians + 4 * 3.1415f / 10) * 30;
shapeY[3] = y + MathUtils.sin(radians + 4 * 3.1415f / 10) * 30;
}
public boolean shouldRemove() {
return remove;
}
public void update(float dt) {
float angle = (float) Math.atan2(target.getPosition().y - y, target.getPosition().x - x); //angle between the follower and target
velocity.set((float) Math.cos(angle) * speed , -speed); //setting direction to follow the target
radians += Math.cos(angle) * dt; //THIS HERE IS MAKING IT ROTATE
x += velocity.x * dt;
y += velocity.y * dt;
setShape();
if(y <= 0 - 60)
remove = true;
else
remove = false;
}
public void draw(ShapeRenderer sp){
sp.setColor(1, 1, 1 ,1);
sp.begin(ShapeRenderer.ShapeType.Line);
for(int i = 0, j = shapeX.length - 1;
i < shapeX.length;
j = i++) {
sp.line(shapeX[i], shapeY[i], shapeX[j], shapeY[j]);
}
sp.end();
}
}
I am not adding the GameScreen because I do not see the need of showing how they are rendered, either way, it'll stay the same.
Also, with the line of code, I am using the Follower points to the player with the bottom vertice as the "eyes"
Thanks for the answers!
Related
I've looked at several examples of people creating tile maps, and I am unable to get the tile position where my mouse is pointed at.
I am using a spritebatch and GameTile[][] to create the map. Keep in mind that the tiles themselves are isometric and not actually a square.
The method renderMap() is where the map is actually is being rendered. createMap() just sets the initial GameTiles for an empty map.
The map is able to be dragged and zoomed in and out using Ortho camera.
Zooming out gives me an issue as well, the tiles seem to be shifted over on click
public class MapEditor implements GameScene {
private GameContext context;
private SpriteBatch batch;
private OrthographicCamera camera;
public static GameTile[][] tiles; //GameTile.WIDTH = 64 & GameTile.HEIGHT =48
public static final int MAP_WIDTH = 20;
public static final int MAP_HEIGHT = 36;
public MapEditor(GameContext context) {
this.context = context;
tiles = new GameTile[MAP_WIDTH][MAP_HEIGHT];
}
#Override
public void create() {
renderer = new ShapeRenderer();
this.batch = new SpriteBatch();
camera = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
}
public void createMap() {
// Create the sea tiles
for (int x = 0; x < MAP_WIDTH; x++) {
for (int y = 0; y < MAP_HEIGHT; y++) {
if (y < 3 || y > 32) {
if(tiles[x][y] == null) {
tiles[x][y] = safezone;
}
}
else {
if(tiles[x][y] == null) {
tiles[x][y] = cell;
}
}
}
}
}
#Override
public void update(){
// update the camera
camera.update();
}
#Override
public void render() {
batch.setProjectionMatrix(camera.combined);
batch.begin();
Gdx.gl.glViewport(0,0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
renderMap();
batch.end();
}
public int getTileX(float x, float y) {
/*
* getRegionWidth() = TILE_WIDTH_HALF
* getRegionHeight() = TILE_HEIGHT_HALF
* these are the ones being added to worldCoords.x/y
*/
Vector3 worldCoords = camera.unproject(new Vector3(x, y, 0));
return (int)((TILE_WIDTH_HALF * ((-TILE_HEIGHT_HALF + (worldCoords.y + TILE_HEIGHT_HALF)) /
TILE_HEIGHT_HALF) + (worldCoords.x + TILE_WIDTH_HALF)) / TILE_WIDTH_HALF) / 2;
}
public int getTileY(float x, float y) {
/*
* getRegionWidth() = TILE_WIDTH_HALF
* getRegionHeight() = TILE_HEIGHT_HALF
* these are the ones being added to worldCoords.x/y
*/
Vector3 worldCoords = camera.unproject(new Vector3(x, y, 0));
return (int)(((-TILE_HEIGHT_HALF * (TILE_WIDTH_HALF + (worldCoords.x + TILE_WIDTH_HALF)) /
TILE_WIDTH_HALF) + (worldCoords.y + TILE_HEIGHT_HALF)) / TILE_HEIGHT_HALF) / 2;
}
#Override
public boolean handleClick(float x, float y, int button) {
int tileX = getTileX(x,y);
int tileY = getTileY(x,y);
System.out.println("Tile:"+tileX + ","+tileY);
}
private void renderMap() {
for (int i = 0; i < tiles.length; i++) {
for(int j = 0; j < tiles[i].length; j++) {
TextureRegion region = tiles[i][j].getRegion();
int x = (i * GameTile.TILE_WIDTH / 2) - (j * GameTile.TILE_WIDTH / 2) - region.getRegionWidth() / 2;
int y = (i * GameTile.TILE_HEIGHT / 2) + (j * GameTile.TILE_HEIGHT / 2) - region.getRegionHeight() / 2;
if (canDraw(x, y, GameTile.TILE_WIDTH, GameTile.TILE_HEIGHT)) {
batch.draw(region, x, y);
}
}
}
}
Actual tile before doing anything to it;
Actual:
Desired:
Converting Cartesian coordinates to isometric is (sort of) done like this:
float isometricX = cartesianX - cartesianY;
float isometricY = (cartesianX + cartesianY) * 0.5f;
The formula needs to be scaled by the height-to-width ratio of the tiles as well and I think that is where it's going wrong in your code.
Given an unprojected worldMousePosition you can get the coordinates and tile coordinates like this:
float r = (float) TILE_HEIGHT / (float) TILE_WIDTH;
float mapx = (worldMousePosition.x / TILE_HEIGHT + worldMousePosition.y / (TILE_HEIGHT * r)) * r;
float mapy = (worldMousePosition.y / (TILE_HEIGHT * r) - (worldMousePosition.x / TILE_HEIGHT)) * r;
worldPosition = new Vector2(mapx - 0.5f, mapy + 0.5f); // -.5/+.5 because the drawing isn't aligned to the tile, it's aligned to the image
int tileX = (int) worldPosition.x;
int tileY = (int) worldPosition.y;
Full source code for the example above:
import com.badlogic.gdx.Game;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.math.Vector3;
public class SandboxGame extends Game {
public static final int TILE_NONE = -1;
public static final int MAP_WIDTH = 20;
public static final int MAP_HEIGHT = 36;
public static final int TILE_WIDTH = 64;
public static final int TILE_HEIGHT = 48;
private SpriteBatch batch;
private OrthographicCamera camera;
private BitmapFont font;
private Vector3 unprojectVector = new Vector3();
private Vector2 worldMousePosition = new Vector2();
private Vector2 worldPosition = new Vector2();
private Texture[] textures;
private int[][] tiles = new int[MAP_WIDTH][MAP_HEIGHT];
#Override
public void create() {
batch = new SpriteBatch();
camera = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
font = new BitmapFont(Gdx.files.internal("default.fnt"), Gdx.files.internal("default.png"), false);
textures = new Texture[] {
new Texture(Gdx.files.internal("tile.png"))
};
for(int x = 0; x < MAP_WIDTH; ++x) {
for(int y = 0; y < MAP_HEIGHT; ++y) {
int rnd = MathUtils.random(10);
if (rnd < 1)
tiles[x][y] = TILE_NONE;
else
tiles[x][y] = 0;
}
}
}
#Override
public void render() {
Gdx.gl.glClearColor(0, 0, 0, 0);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
float scrollSpeed = 64;
float zoomSpeed = 2;
float delta = Gdx.graphics.getDeltaTime();
if (Gdx.input.isKeyPressed(Input.Keys.A))
camera.position.x -= delta * scrollSpeed;
if (Gdx.input.isKeyPressed(Input.Keys.D))
camera.position.x += delta * scrollSpeed;
if (Gdx.input.isKeyPressed(Input.Keys.W))
camera.position.y += delta * scrollSpeed;
if (Gdx.input.isKeyPressed(Input.Keys.S))
camera.position.y -= delta * scrollSpeed;
if (Gdx.input.isKeyPressed(Input.Keys.Q))
camera.zoom = Math.min(camera.zoom + zoomSpeed * delta, 8.0f);
if (Gdx.input.isKeyPressed(Input.Keys.E))
camera.zoom = Math.max(camera.zoom - zoomSpeed * delta, 0.5f);
camera.update();
int mx = Gdx.input.getX();
int my = Gdx.input.getY();
camera.unproject(unprojectVector.set(mx, my, 0.0f));
worldMousePosition.set(unprojectVector.x, unprojectVector.y);
float r = (float) TILE_HEIGHT / (float) TILE_WIDTH;
float mapx = (worldMousePosition.x / TILE_HEIGHT + worldMousePosition.y / (TILE_HEIGHT * r)) * r;
float mapy = (worldMousePosition.y / (TILE_HEIGHT * r) - (worldMousePosition.x / TILE_HEIGHT)) * r;
worldPosition = new Vector2(mapx - 0.5f, mapy + 0.5f); // -.5/+.5 because the drawing isn't aligned to the tile, it's aligned to the image
int tileX = (int) worldPosition.x;
int tileY = (int) worldPosition.y;
batch.setProjectionMatrix(camera.combined);
batch.begin();
for (int col = MAP_WIDTH - 1; col >= 0; --col) {
for (int row = MAP_HEIGHT - 1; row >= 0; --row) {
if (tiles[col][row] != TILE_NONE) {
Texture texture = textures[tiles[col][row]];
int x = (col * TILE_WIDTH / 2) - (row * TILE_WIDTH / 2);
int y = (col * TILE_HEIGHT / 2) + (row * TILE_HEIGHT / 2);
batch.setColor(col == tileX && row == tileY ? Color.GRAY : Color.WHITE);
batch.draw(texture, x, y);
}
}
}
if (Gdx.input.isKeyPressed(Input.Keys.SPACE)) {
for (int col = MAP_WIDTH - 1; col >= 0; --col) {
for (int row = MAP_HEIGHT - 1; row >= 0; --row) {
int x = (col * TILE_WIDTH / 2) - (row * TILE_WIDTH / 2);
int y = (col * TILE_HEIGHT / 2) + (row * TILE_HEIGHT / 2);
font.draw(batch, String.format("(%d, %d)", col, row), x, y);
}
}
}
String str = String.format("World position (%.2f, %.2f), Tile (%d, %d)", worldPosition.x, worldPosition.y, (int)worldPosition.x, (int)worldPosition.y);
font.draw(batch, str, worldMousePosition.x, worldMousePosition.y);
batch.end();
}
}
I cant respond to bornander's post, but my tweak would be at
int tileX = (int) Math.Floor(worldPosition.x);
int tileY = (int) Math.Floor(worldPosition.y);
Where simple (int) cast will provide wrong position around 0 with negative values, if there are tiles, while using Math.Floor will work as intended.
I am making a 2D top-down shooter in Java (uni project) but hit a problem with bullet aiming - I am unsure why the angle is incorrect, and how to correct it.
The player shoots bullets at the cursor location on mousedown. I am using dx/y = (x/ytarget - x/yorigin), normalising and incrementing the bullets x/y pos with dx each tick.
When the cursor is moved, the firing angle tracks the cursor - but the angle is off by 45 degrees or so The white circle is player, red is cursor and bullets the yellow dots.
I dont have rep to post images (first post), here is a link that shows the error of the angle.
http://i.imgur.com/xbUh2fX
Here is the bullet class:
note - update() is called by the main game loop
import java.awt.*;
import java.awt.MouseInfo;
public class Bullet {
private double x;
private double y;
private int r;
private double dx;
private double dy;
private double speed;
private double angle;
private Point c;
private Color color1;
public Bullet(int x, int y) {
this.x = x;
this.y = y;
r = 3;
speed = 30;
color1 = Color.YELLOW;
c = MouseInfo.getPointerInfo().getLocation();
// getting direction
dx = c.x - x;
dy = c.y - y;
double distance = Math.sqrt(dx*dx + dy*dy);
dx /= distance;
dy /= distance;
}
public boolean update() {
x += dx*speed;
y += dy*speed;
if(x < -r || x > GamePanel.WIDTH + r ||
y < -r || y > GamePanel.HEIGHT + r) {
return true;
}
return false;
}
public void draw(Graphics2D g) {
g.setColor(color1);
g.fillOval((int) (x - r), (int) (y - r), 2 * r, 2 * r);
}
}
I got a similar game and this is the code I used
import java.awt.Graphics2D;
import araccoongames.pongadventure.game.Entity;
import araccoongames.pongadventure.game.Game;
import araccoongames.pongadventure.game.MapLoader;
public class Ball extends Entity {
private float speed = 8;
private float speedx;
private float speedy;
private float degree;
public Ball(float posx, float posy, Game game) {
super(0, 0, game);
this.posx = posx;
this.posy = posy;
// posx = ball x position
// posy = ball y position
// game.input.MOUSEY = mouse y position
// game.input.MOUSEX = mouse x position
degree = (float) (270 + Math.toDegrees(Math.atan2(posy - game.input.MOUSEY, posx - game.input.MOUSEX))) % 360;
speedx = (float) (speed * Math.sin(Math.toRadians(degree)));
speedy = (float) (speed * Math.cos(Math.toRadians(degree)));
}
#Override
public void render(Graphics2D g) {
drawImage(game.texture.SPRITE[0][1], g);
}
#Override
public void update() {
posx += speedx;
posy -= speedy;
}
}
Hello :) I'm totally lost. I have two balls on the screen, floating. Also I have a method that checks is there is a collision and a method name 'collide' that collides :)
When both balls goes in a straight line on each other it collides well. The problem is shown on the picture:
So, the methods are:
public final float ball_radius = 2.4f; // ball image has 48 width
public boolean isColliding(Ball ball)
{
distance = Math.sqrt((ball.image_center_x - this.image_center_x)*(ball.image_center_x - this.image_center_x)+(ball.image_center_y - this.image_center_y)*(ball.image_center_y - this.image_center_y));
if(distance <= 2*ball_radius)
return true;
/*
float sumRadius = 9.6f;
float sqrRadius = sumRadius * sumRadius;
float distSqr = (xd * xd) + (yd * yd);
if (distSqr <= sqrRadius)
{
return true;
}*/
return false;
}
void Collide(Ball ball1, Ball ball2)
{
double dx = (ball1.x - ball2.x) + dt * (ball1.vx - ball2.vx);
double dy = (ball1.y - ball2.y) + dt * (ball1.vy - ball2.vy);
// if collision swap velocities
if (Math.sqrt(dx * dx + dy * dy) <= 2*ball_radius) {
double tempx = ball1.vx;
double tempy = ball1.vy;
ball1.vx = ball2.vx;
ball1.vy = ball2.vy;
ball2.vx = tempx;
ball2.vy = tempy;
}
}
private void moveBalls(){
for (int i = 0; i < balls.size(); i++) {
Ball ball1 = balls.get(i);
for (int a = i + 1; a < balls.size(); a++) {
Ball ball2 = balls.get(a);
if(ball1.isColliding(ball2)) {
ball1.Collide(ball1, ball2);
checkHealthAndChangeColor(ball1, ball2);
}
//catchMP.start();
}
}
for (int i = 0; i < balls.size(); i++) {
balls.get(i).step();
}
}
I am using the following code to generate a sine wave:
The speed of this animation is slow-fast-slow.
Code:
public static final double SINE_TO_180 = 114.58865012930961, TIMES = 180, SINE_OF_90 = Math.sin(Math.toRadians(90));
public static void main(String[] args) throws Exception{
float velc = 200;
float angle = 45;
float resistance = 0f;
double multiple = (velc * 2.5 / SINE_TO_180);
int offset = 0;
double y = 0;
double x = 0;
double h = 0;
double cos = Math.cos(Math.toRadians(angle));
double sin = Math.sin(Math.toRadians(angle));
for(int i = offset; i < TIMES + 1 + offset; i ++){
y += ((Math.sin(Math.toRadians(i * 2)))) * multiple * sin;
if(y >= h)
h = y;
x += Math.sin(Math.toRadians(i)) * multiple * ((1 - resistance) * 1.5) * Math.abs(cos);
// x += multiple * cos;
// if(i + offset < TIMES / 2){
// x += Math.sin(Math.toRadians(i)) * multiple * ((1 - resistance) * 1.5);
// }else{
// x += Math.sin(Math.toRadians(TIMES / 2)) * multiple * (1 - resistance);
// }
}
y = Math.round(y);
//do round x?
x = Math.round(x);
System.out.println("X: " + x);
JFrame frm = new JFrame("Projectile!");
frm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
BufferedImage b = new BufferedImage((int)x + 1, (int)h + 1, BufferedImage.TYPE_INT_RGB);
Graphics g = b.getGraphics();
y = 0;
x = 0;
JLabel l = new JLabel(new ImageIcon(b));
frm.add(l);
frm.pack();
frm.setVisible(true);
for(int i = offset; i < TIMES + 1 + offset; i ++){
y += ((Math.sin(Math.toRadians(i * 2)))) * multiple * sin;
x += Math.sin(Math.toRadians(i)) * multiple * ((1 - resistance) * 1.5) * Math.abs(cos);
// x += multiple * cos;
// if(i + offset < TIMES / 2){
// x += Math.sin(Math.toRadians(i)) * multiple * ((1 - resistance) * 1.5);
// }else{
// x += Math.sin(Math.toRadians(TIMES / 2)) * multiple * (1 - resistance);
// }
g.setColor(Color.red);
g.drawLine((int)x, (int)(h - y), (int)x, (int)(h - y));
l.setIcon(new ImageIcon(b));
frm.repaint();
Thread.sleep((int)(1000.0 / 24.0));
}
ImageIO.write(b, "png", new File("C:\\proj.png"));
}
Now I would like to change the sine animation to fast-slow-fast where it is slow at its peak so I tried the following result and got this: I would expect it to be the same just the animation speed different. Code:
public static void main(String[] args) throws Exception{
float velc = 200;
float angle = 45;
float resistance = 0f;
double multiple = (velc * 2.5 / SINE_TO_180);
int offset = 0;
double y = 0;
double x = 0;
double h = 0;
double cos = Math.cos(Math.toRadians(angle));
double sin = Math.sin(Math.toRadians(angle));
for(int i = offset; i < TIMES + 1 + offset; i ++){
y += (1 - Math.sin(Math.toRadians(i * 2))) * multiple * sin;
if(y >= h)
h = y;
// x += Math.sin(Math.toRadians(i)) * multiple * ((1 - resistance) * 1.5) * Math.abs(cos);
x += 2;
// x += multiple * cos;
// if(i + offset < TIMES / 2){
// x += Math.sin(Math.toRadians(i)) * multiple * ((1 - resistance) * 1.5);
// }else{
// x += Math.sin(Math.toRadians(TIMES / 2)) * multiple * (1 - resistance);
// }
}
y = Math.round(y);
//do round x?
x = Math.round(x);
System.out.println("X: " + x);
JFrame frm = new JFrame("Projectile!");
frm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
BufferedImage b = new BufferedImage((int)x + 1, (int)h + 1, BufferedImage.TYPE_INT_RGB);
Graphics g = b.getGraphics();
y = 0;
x = 0;
JLabel l = new JLabel(new ImageIcon(b));
frm.add(l);
frm.pack();
frm.setVisible(true);
for(int i = offset; i < TIMES + 1 + offset; i ++){
y += (1 - Math.sin(Math.toRadians(i * 2))) * multiple * sin;
x += 2;
// x += Math.sin(Math.toRadians(i)) * multiple * ((1 - resistance) * 1.5) * Math.abs(cos);
// x += multiple * cos;
// if(i + offset < TIMES / 2){
// x += Math.sin(Math.toRadians(i)) * multiple * ((1 - resistance) * 1.5);
// }else{
// x += Math.sin(Math.toRadians(TIMES / 2)) * multiple * (1 - resistance);
// }
g.setColor(Color.red);
g.drawLine((int)x, (int)(h - y), (int)x, (int)(h - y));
l.setIcon(new ImageIcon(b));
frm.repaint();
Thread.sleep((int)(1000.0 / 24.0));
}
ImageIO.write(b, "png", new File("C:\\proj2.png"));
}
Anyone know what I am doing wrong because I expect the result to be the same as the first just different animation speeds?
if you want to have a smooth animation i would seperate the data and the animation;
first create your data - it is a (mathematical) function [meaning f(x)->y], so you can simply use an array for data
private int endOfX = 100; //adjust as you wish
private int[] data;
public void calculateData(){
data = new int[amendOfX ountPixels];
for(int x = 0; x < endOfX ; x++){
y = x*x; //this is an example, use your mathematical function here
}
}
so - now you can easily use this data to provide a smooth animation
public class AnimationOfFunction(){
public static void main(String[] args){
new AnimationOfFunktion().createAndShowGui(); //as from java tutorials
}
private BufferedImage img;
private Graphics gr;
private void createAndShowGui(){
calculateData(); first of all we create the data!
JFrame frame = new JFrame();//then create your frame here
JPanel panel = createContent(); //create your drawing panel here
frame.add(panel);//adding drawing panel
frame.pack(); //setting the proper size of frame
frame.setVisible(true); //show frame
startAnimation(panel); //this is important - after showing the frame you start your animation here!
}
}
so - this would be the start of you application, what to do now? first create a proper drawing panel:
private JPanel createContent(){
//create a anonym class
#surpress serial
JPanel panel = new JPanel(){
#override
public void paintComponent(Graphics gr){
super.paintComponent(gr);
gr.drawImage(img, 0,0, null);
}
}
panel.setPreferredSize(new Dimension(img.getWidth(), img.getHeight() ));
return panel;
}
and most important - you have to start the animation:
private void startAnimation(final JPanel panel){
//create a anonym class
Runnable r = new Runnable(){
private int py = 0; //previous values
private int py = 0; //previous values
#overrdie
public void run(){
for(int x = 0; x < endOfX ; x++){
int y = data[x];
//now we have x and y, so you can plot your function;
gr.drawLine(px, py, x,y); //you can scale here
int sleeptime = calculateSleepTime(px,py, x,y);
Thread.sleep(sleeptime);
//set the previouse values;
px = x;
py = y;
//important - repaint your panel to create an 'animation'
panel.repaint();
}
}
}
//having that runnable we must start that runnable within an thread
Thread thread = new Thread(r);
thread.setDaemon(true);
thread.start();
}
so whats left to do? we must calculate the sleep time: if the distance between two points is 'big' we sleep longer, if the distance is short, we sleep less...
public int calculateSleeptime(int px, int py, int x, int y){
int distance = (y-py)*(y-py)+(x-px)*(x-px);
distance = (int)(Math.sqrt(distance);
int sleepTime = distance*100; //play with this value!
return sleeptime;
}
I have written that code all out of my head, i didn't have any IDE to check if it contains any spelling errors or compiling errors, please do that for yourself, as well as i didn't initiate the BufferedImage img ang Graphics gr. but obvious you can do that already!
I am using Slick and Tiled2D to make a top-down RPG style game. I am trying to do collision, but the player seems to be able to go through blocks that are on the left side of a building, or the left half of a block. The full project is here: http://github.com/Cj1m/RPG
Here is my code for the player movement and collision detection:
#Override
public void update(GameContainer gc, int delta) throws SlickException {
input = gc.getInput();
if(input.isKeyDown(Input.KEY_W)){
if(!isBlocked(x, y - delta * 0.1f)){
y-=0.1 * delta;
timer(0,1,delta);
}
}else if(input.isKeyDown(Input.KEY_S) && y < screenBottomEdge){
if (!isBlocked(x, y + playerHeight + delta * 0.1f)){
y+=0.1 * delta;
timer(0,0,delta);
}
}else if(input.isKeyDown(Input.KEY_A) && x > screenLeftEdge){
if (!isBlocked(x - delta * 0.1f, y)){
x-=0.1 * delta;
timer(0,2,delta);
}
}else if(input.isKeyDown(Input.KEY_D) && x < screenRightEdge){
if (!isBlocked(x + playerWidth + delta * 0.1f, y)){
x+=0.1 * delta;
timer(0,3,delta);
}
}
}
and
private boolean isBlocked(float x, float y) {
int xBlock = (int)x / 30;
int yBlock = (int)y / 30;
return blocked[xBlock][yBlock];
}
I guess the x and y in isBlocked are the player's pixel-accurate x and y-positions, while xBlock and yBlock are the tile-accurate positions.
When you say they go through half of the block this seems to me like a rounding-problem at
int xBlock = (int)x / 30;
int yBlock = (int)y / 30;
Try something along the lines of
(int) Math.round(x/30.0);