I'm having troubles having my character stop once it hits the edges of the windows.
Here's my update method.
public void update(GameContainer gc, StateBasedGame sbg, int delta)
{
Input input = gc.getInput();
playerX += VelocityX;
gc.setShowFPS(Splash.showFps);
if(input.isKeyPressed(Input.KEY_F1))
{
Splash.showFps = !Splash.showFps;
}
if (input.isKeyDown(Input.KEY_RIGHT))
VelocityX = 10;
else if (input.isKeyDown(Input.KEY_LEFT))
VelocityX = -10;
else if (playerX >= 700)
VelocityX = 0;
else
{
VelocityX = 0;
}
}
I realize going off to left is occurring because I haven't coded it yet but the character goes off the screen the right
if (input.isKeyDown(Input.KEY_RIGHT)){
VelocityX = 10;}
else if (input.isKeyDown(Input.KEY_LEFT)){
VelocityX = -10;}
else{VelocityX = 0;}
if (playerX >699){
playerX=699;
VelocityX = 0;}
else if(playerX<1){
playerX=1;VelocityX = 0;
}
Problem fixed. Within the key detection you set the velocity to 0.
So instead
if (input.isKeyDown(Input.KEY_RIGHT))
VelocityX = 10;
else if (playerX >= 700)
VelocityX = 0;
Do something like
if (input.isKeyDown(Input.KEY_RIGHT))
{
VelocityX = 10;
if (playerX >= 700)
VelocityX = 0;
}
There are a couple things wrong I noticed. The first is your update issue: you want to player to move by their velocity. You also need to do your bounds checking. Another problem you have, that others haven't noted on, is that you have a right key preference, That means that if you are holding the right and left key, the player moves right. This is due to the if / else if statements. You should separate your ifs out for a more granular level of control:
public void update(GameContainer gc, StateBasedGame sbg, int delta)
{
Input input = gc.getInput();
//playerX += VelocityX; -> this is moved
gc.setShowFPS(Splash.showFps);
if(input.isKeyPressed(Input.KEY_F1))
{
Splash.showFps = !Splash.showFps;
}
VelocityX = 0;
if (input.isKeyDown(Input.KEY_RIGHT))
VelocityX += 10;
//removed the else
if (input.isKeyDown(Input.KEY_LEFT))
VelocityX -= 10;
//you want to bounds check regardless of the above statments
//get rid of the else
if ((playerX >= 700 && VelocityX > 0) || (playerX <= 0 && VelocityX < 0)) //check both sides
VelocityX = 0;
//move the player
playerX += VelocityX;
}
EDIT: Modified my code to fix the issue of being unable to move when at a boundary.
Related
I added a thing to my game, so that when you press space you'll get a small speed boost. However, it only works correctly when you use the WASD keys. If you press the up and left or down and right arrowkeys, the boost won't work, but otherwise it does. Can anyone explain why it does that?
Here's the code:
boostTimer += Gdx.graphics.getDeltaTime();
if(boostTimer > 3){
snailBoost = 0;
boostTimer = 0;
}
//movement
if(Gdx.input.isKeyPressed(Keys.LEFT) || Gdx.input.isKeyPressed(Keys.A)){
if(Gdx.input.isKeyPressed(Keys.SPACE) && snailBoost < 20){
snailBoost++;
snail.getBounds().x -= (snailSpeed + 100) * delta;
}
//flips the sprite
snail.getSprite().setFlip(false, true);
snail.getBounds().x -= snailSpeed * delta;
//handles what happens when you go outside the game world
if(snail.getBounds().x < -100)snail.getBounds().x = 1920;
}
if(Gdx.input.isKeyPressed(Keys.RIGHT) || Gdx.input.isKeyPressed(Keys.D)){
if(Gdx.input.isKeyPressed(Keys.SPACE) && snailBoost < 20){
snailBoost++;
snail.getBounds().x += (snailSpeed + 100) * delta;
}
snail.getSprite().setFlip(true, true);
snail.getBounds().x += snailSpeed * delta;
if(snail.getBounds().x > 2020)snail.getBounds().x = -100;
}
if(Gdx.input.isKeyPressed(Keys.UP) || Gdx.input.isKeyPressed(Keys.W)){
if(Gdx.input.isKeyPressed(Keys.SPACE) && snailBoost < 20){
snailBoost++;
snail.getBounds().y -= (snailSpeed + 100) * delta;
}
snail.getBounds().y -= snailSpeed * delta;
if(snail.getBounds().y < -100)snail.getBounds().y = 1080;
}
if(Gdx.input.isKeyPressed(Keys.DOWN) || Gdx.input.isKeyPressed(Keys.S)){
if(Gdx.input.isKeyPressed(Keys.SPACE) && snailBoost < 20){
snailBoost++;
snail.getBounds().y += (snailSpeed + 100) * delta;
}
snail.getBounds().y += snailSpeed * delta;
if(snail.getBounds().y > 1080)snail.getBounds().y = -100;
}
Sorry for messy code. :P
Still new to game development.
Cheap keyboards share the control lines of the keys, so some key combinations won't register correctly and trying to press more than 3-4 keys at once will result in nothing happening.
Either buy a more expensive keyboard, or choose keys so they work (such as the famous WASD you've already noticed works). Nothing to do with code.
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.
I am making a simple platform game in Libgdx... in which I have made the player to move left, move right and jump. The code works fine on Desktop but on Android devices, Jump is not fired when the player moves left or right. It looks strange. Here is my code...
private void updatePlayerForUserInput(float deltaTime)
{
// check input and apply to velocity & state
if ((Gdx.input.isKeyPressed(Keys.SPACE) || isTouched(0.87f, 1,0,1f)) && world.player.grounded)
{
world.player.velocity.y += world.player.JUMP_VELOCITY;
world.player.state =2;
world.player.grounded = false;
}
if (Gdx.input.isKeyPressed(Keys.LEFT) || Gdx.input.isKeyPressed(Keys.A) || isTouched(0, 0.1f,0,1f))
{
world.player.velocity.x -=world.player.MAX_VELOCITY;
if (world.player.grounded)
world.player.state =1;
world.player.facesRight = false;
}
if (Gdx.input.isKeyPressed(Keys.RIGHT) || Gdx.input.isKeyPressed(Keys.D) || isTouched(0.2f, 0.3f,0,1f))
{
world.player.velocity.x =world.player.MAX_VELOCITY;
if (world.player.grounded)
world.player.state =1;
world.player.facesRight = true;
}
}
private boolean isTouched(float startX, float endX , float startY, float endY)
{
// check if any finge is touch the area between startX and endX
// startX/endX are given between 0 (left edge of the screen) and 1 (right edge of the screen)
for (int i = 0; i < 2; i++)
{
float x = Gdx.input.getX() / (float) Gdx.graphics.getWidth();
float y = Gdx.input.getY() / (float) Gdx.graphics.getHeight();
if (Gdx.input.isTouched(i) && (x >= startX && x <= endX) && (y>=startY && y<= endY))
{
return true;
}
}
return false;
}
I took the idea from the demo platform game SuperKoalio by mzencher at
https://github.com/libgdx/libgdx/blob/master/tests/gdx-tests/src/com/badlogic/gdx/tests/superkoalio/SuperKoalio.java
Please suggest
This code:
float x = Gdx.input.getX() / (float) Gdx.graphics.getWidth();
float y = Gdx.input.getY() / (float) Gdx.graphics.getHeight();
Is always getting the x/y from the first active touch. You need to check the "i'th" active touch. Like this:
for (int i = 0; i < 20; i++) {
if (Gdx.input.isTouched(i)) {
float x = Gdx.input.getX(i) / (float) Gdx.graphics.getWidth();
float y = Gdx.input.getY(i) / (float) Gdx.graphics.getHeight();
if ((x >= startX && x <= endX) && (y>=startY && y<= endY)) {
return true;
}
}
return false;
Also, you should probably iterate through all 20 possible touch points, since up to 20 touch points can be tracked by the hardware. (Try putting three fingers in the "jump" region and then add a fourth finger in the "move left" region.)
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.
Myself shweta dodiya.I am having an problem related to sensor and logic in j2me which i had implemented for achieving the result in my project.The logic which i had implemented is as follows:-
sensor= (SensorConnection) Connector.open("sensor:acceleration");
try {
data = sensor.getData(1);
} catch (IOException ex) {
ex.printStackTrace();
}
for (int i = 0; i < data.length - 1; i++) {
value[i] = data[i].getDoubleValues()[0];
}
CurrentValX = value[0];//X-axis of sensor
CurrentValY = value[1];//y-axis of sensor
if (CurrentValX < PreValueX1) {
left = false;
right = true;
} else if (CurrentValX > PreValueX1) {
left = true;
right = false;
}
if (CurrentValY < PreValueY1) {
down = false;
up = true;
} else if (CurrentValY > PreValueY1) {
down = true;
up = false;
}
if (right == true && ballX < Scrwidth - 15) {
ballX += 4;
} else if (left == true && ballX > 15) {
ballX -= 4;
}
if (down == true && ballY < Scrheight - 15) {
ballY += 4;
} else if (up == true && ballY > 15) {
ballY -= 4;
}
CurrentValY = PreValueY1;
CurrentValX = PreValueX1;
//check for the collision of ball with the other object like brick
if (bricksprite.collidesWith(ballSprite, true)) {
if (right) {
ballX -= 10;
}
if (left) {
ballX += 10;
}
if (up) {
ballY += 10;
}
if (down) {
ballX -= 10;
}
}
The problem i am having is in the collision of the ball and the bricks.when it get collide i want to move ball in the opposite direction of the collision.But sometime the ball instead of moving in opposite direction it keep moving in same direction.I had getting the direction of the ball through the boolean up,down,left,right.
Please help me to solve it and guide me and correct me if i m wrong somewhere
Thanks in advance
I haven't read your code , But in past I have coded the same kinda game,
In that I have applied following logic;
1.when ball colides suppose consider ball is moving from right to left than collides at left wall at some angel. here your x and y was decreasing in uniform manner upon colission your x should increase while y should be decreasing with the same fashion.
2.when ball colides vertical wall , y should invert x should be same..
I hope it clears up the logic.