Check if a player is moving or not - java

I'm creating a plugin for an event, this event is just: when you stop moving, you loose. I created everything, but my check to know if a player moves or not doesn't work:
I tried to make an array and when a player move event it's added, but it doesn't work,
#EventHandler
public static void OnPlayerMoov(PlayerMoveEvent e) {
if(!playerHaveMooved.contains(e.getPlayer())) {
playerHaveMooved.add(e.getPlayer());
}
}
public static boolean isMoving(Player p){
System.out.println(Respawn.playerHaveMooved.contains(p));
return Respawn.playerHaveMooved.contains(p);
}
I tried to use velocity; it doesn't work,
public static boolean isMoving(Player p){
return (p.getVelocity().length() == 0);
}
It doesn't work. It kills me when I am moving.
Do you have a solution?

The first don't work because you just check if the player already move a time, which will always be true.
The second about velocity check only if player get knockbacked for example.
First solution
Save last time of move, and check each few time if it stop move.
In this example, I will force player to move each seconds.
private final HashMap<Player, Long> timeMove = new HashMap<>(); // map for data
#Eventhandler
public void onMove(PlayerMoveEvent e) {
timeMove.put(e.getPlayer(), System.currentTimeMillis()); // update last move
}
public void startChecking(JavaPlugin pl) {
pl.getServer().getScheduler().runTaskTimer(pl, () -> {
long current = System.currentTimeMillis();
for(Player p : Bukkit.getOnlinePlayers()) {
long last = timeMove.getOrDefault(p, 0);
long diff = current - last;
if(diff > 1000) { // 1000 = second
// player don't move
}
}
}, 20, 20);
}
Second solution
Check each X time from last and current location
private final HashMap<Player, Location> lastLoc = new HashMap<>(); // map for data
public void startChecking(JavaPlugin pl) {
pl.getServer().getScheduler().runTaskTimer(pl, () -> {
for(Player p : Bukkit.getOnlinePlayers()) {
Location lastPlayerLoc = lastLoc.get(p); // get loc, or keep null if not registered
if(lastPlayerLoc != null) {
double distance = lastPlayerLoc.distance(p.getLocation());
if(distance == 0.0) {
// here the player don't move
continue; // go to next player
}
}
lastLoc.put(p, p.getLocation()); // update loc
}
}, 20, 20);
}

Related

Procedural Generated Rooms (Like Binding of Isaac)

I'm making a simple procedural generated dungeon where your character spawns in a room with randomly opened or closed doors in random direction. This is already complete.
When the character leaves the room it will generate new random numbers for a new room. Storing the numbers of the old room and to generate a room with those numbers if the character travels backwards. This part isn't finished, but would be easy to do, but I don't want to do that yet, because it will cause the problem below.
How could I create something that could store that no matter where the player travels and know when to use the variables? How could I automatically create variables like that?
Current Code:
public class Executable extends JFrame implements KeyListener {
Container contentPane=this.getContentPane();
Graphics bufferGraphics;
int xAxis; //Universal Variables:
int yAxis;
int characterX=463;
int characterY=486;
int oldCharacterX=463;
int oldCharacterY=486;
Image characterNorth = CustomImages.createImageIcon("Images/characterNorth.jpg").getImage();
Image characterEast = CustomImages.createImageIcon("Images/characterEast.jpg").getImage();
Image characterSouth = CustomImages.createImageIcon("Images/characterSouth.jpg").getImage();
Image characterWest = CustomImages.createImageIcon("Images/characterWest.jpg").getImage();
Image brickWall = CustomImages.createImageIcon("Images/brickWall.jpg").getImage();
Image brickFloor = CustomImages.createImageIcon("Images/brickFloor.jpg").getImage();
Image character=characterNorth;
boolean pressed=false;
static boolean northDoor;
static boolean eastDoor;
static boolean southDoor;
static boolean westDoor;
static boolean Randomizer=true;
static int north;
static int east;
static int south;
static int west;
static Random r=new Random();
boolean doorOpen=false;
public static void main(String[] args) { //Main
north=r.nextInt(3)+1;
east=r.nextInt(3)+1;
south=r.nextInt(3)+1;
west=r.nextInt(3)+1;
if(north==1) {
northDoor=true;
}else {
northDoor=false;
}
if(east==1) {
eastDoor=true;
}else {
eastDoor=false;
}
if(south==1) {
southDoor=true;
}else {
southDoor=false;
}
if(west==1) {
westDoor=true;
}else {
westDoor=false;
}
Executable e=new Executable();
}
public Executable() { //Canvas
this.setBounds(0, 0, 1680, 1050);
this.setVisible(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
addKeyListener(this);
setFocusable(true);
requestFocusInWindow();
}
public void paint(Graphics g) { //Paint
for(xAxis=58;xAxis<=858;xAxis=xAxis+50) {
for(yAxis=81;yAxis<=881;yAxis=yAxis+50) {
g.drawImage(brickFloor,xAxis,yAxis,null);
}
yAxis=31;
}
for(xAxis=8;xAxis<958;xAxis=xAxis+50) {
g.drawImage(brickWall,xAxis,yAxis,null);
}
yAxis=931;
for(xAxis=8;xAxis<=908;xAxis=xAxis+50) {
g.drawImage(brickWall,xAxis,yAxis,null);
}
xAxis=8;
for(yAxis=81;yAxis<=881;yAxis=yAxis+50) {
g.drawImage(brickWall,xAxis,yAxis,null);
}
xAxis=908;
for(yAxis=81;yAxis<=881;yAxis=yAxis+50) {
g.drawImage(brickWall,xAxis,yAxis,null);
}
while(!doorOpen) {
if(northDoor==false && eastDoor==false && southDoor==false && westDoor==false) {
north=r.nextInt(3)+1;
east=r.nextInt(3)+1;
south=r.nextInt(3)+1;
west=r.nextInt(3)+1;
if(north==1) {
northDoor=true;
}else {
northDoor=false;
}
if(east==1) {
eastDoor=true;
}else {
eastDoor=false;
}
if(south==1) {
southDoor=true;
}else {
southDoor=false;
}
if(west==1) {
westDoor=true;
}else {
westDoor=false;
}
}else {
doorOpen=true;
}
}
if(northDoor) {
g.drawImage(brickFloor,458,31,null);
}
if(eastDoor) {
g.drawImage(brickFloor,908,481,null);
}
if(southDoor) {
g.drawImage(brickFloor,458,931,null);
}
if(westDoor) {
g.drawImage(brickFloor,8,481,null);
}
g.drawImage(character,characterX,characterY,null);
}
#Override
public void keyPressed(KeyEvent arg0) { //Character rotation and movement.
if(pressed==false) {
pressed=true;
if(arg0.getKeyCode() == KeyEvent.VK_W){
if(character==characterNorth) {
if(characterY>86 && characterX>13 && characterX<913) {
characterY=characterY-50;
}else if(northDoor && characterX==463) {
oldCharacterY=characterY;
characterY=characterY-50;
}
}else {
character=characterNorth;
}
}
if(arg0.getKeyCode() == KeyEvent.VK_A){
if(character==characterWest && characterY>36 && characterY<926) {
if(characterX>63) { //and y is greater than and less than
oldCharacterX=characterX;
characterX=characterX-50;
}else if(westDoor && characterY==486) {
oldCharacterX=characterX;
characterX=characterX-50;
}
}else {
character=characterWest;
}
}
if(arg0.getKeyCode() == KeyEvent.VK_S){
if(character==characterSouth) {
if(characterY<871 && characterX>13 && characterX<913) {
oldCharacterY=characterY;
characterY=characterY+50;
}else if(southDoor && characterX==463) {
oldCharacterY=characterY;
characterY=characterY+50;
}
}else {
character=characterSouth;
}
}
if(arg0.getKeyCode() == KeyEvent.VK_D){
if(character==characterEast && characterY>36 && characterY<926) {
if(characterX<848) { //and y is greater than and less than
oldCharacterX=characterX;
characterX=characterX+50;
}else if(eastDoor && characterY==486) {
oldCharacterX=characterX;
characterX=characterX+50;
}
}else {
character=characterEast;
}
}
repaint(oldCharacterX,oldCharacterY,40,40);
repaint(characterX,characterY,40,40);
}
}
#Override
public void keyReleased(KeyEvent arg0) { //Prevents keys from being held down.
if(arg0.getKeyCode() == KeyEvent.VK_W){
pressed=false;
}
if(arg0.getKeyCode() == KeyEvent.VK_A){
pressed=false;
}
if(arg0.getKeyCode() == KeyEvent.VK_S){
pressed=false;
}
if(arg0.getKeyCode() == KeyEvent.VK_D){
pressed=false;
}
}
#Override
public void keyTyped(KeyEvent arg0) {
// TODO Auto-generated method stub
}
}
Hopefully this will help a bit. I would suggest you have a game state, this handles drawing, moving, key events like your current Executable class.
Basic overview of what is below. The GameState has a reference to a currentRoomState this is what you should deem the character is in. Upon moving to a door, you will need to check for this, the call to currentRoomState.MoveToNextRoom() with the appropreate parameters.
This will trigger the current room state to generate a new room, set the reference to the new room to be tied to the correct door, place the character at the correct door in the new room, tie a refernce to the old room in the new room and set the current room to the new room.
When you move to a door that has a previous room tied to it, the variables will have been persisted.
Best of luck
-Chris
eg:
class GameState{
RoomState startingRoomState = new RoomState();
RoomState currentRoomState = startingRoomState;
public void move(int x, int y)
{
currentRoomState.iCharacterPosX += x;
currentRoomState.iCharacterPosY += y;
// Check if need to move to a new room (eg move north)
currentRoomState = currentRoomState.MoveToNextRoom(true, false, false, false);
}
public void draw()
{
//Based on the character pos and draw variables in currentRoomState
}
}
And then you have a room state, which describes a room
class RoomState{
//Where the doors are
boolean northDoor = false;
boolean eastDoor = false;
boolean southDoor = false;
boolean westDoor = false;
// Reference to the room adjacent rooms
RoomState rs_NorthDoor = null;
RoomState rs_EastDoor = null;
RoomState rs_SouthDoor = null;
RoomState rs_WestDoor = null;
int iCharacterPosX = 0;
int iCharacterPosY = 0;
// Initial
RoomState(){
northDoor = true; eastDoor = true; southDoor = true; westDoor = true;
}
RoomState(RoomState prevState, boolean north, boolean east, boolean south, boolean west){
// Randomise door states
// Put character in the position he should be
iCharacterPosX = 0;//right most x Coord - oldX
iCharacterPosX = 0;//bottom most y Coord - oldy
if(north)
{
rs_NorthDoor = prevState;
} //elseif other doors
}
public RoomState MoveToNextRoom(boolean north, boolean east, boolean south, boolean west){
if(north){
if(rs_NorthDoor == null)
{
rs_NorthDoor = new RoomState(this, north, east, south, west);
}
return rs_NorthDoor;
} //else if the others
return null;
}
}
If you are looking to store the random number associated with each room and then traverse backward, in order, through the random numbers, a stack is the data structure you are looking for. To gain a conceptual understanding of a stack, see Stack (abstract data type). In short, a stack is like a pile of papers, where the last item placed at the top of the pile is the first element removed from the pile when traversing through the papers, termed Last-in-First-out (LIFO) ordering.
In Java, a Deque (double-ended queue, pronounced "deck") can be used as a stack. To put an element on the top of the stack, you use the push method and remove an element from the top of the stack, you use the pop method (note that pop both obtains the value at the top of the stack and removes it from the stack). For example:
Deque<Integer> stack = new ArrayDeque<>();
stack.push(10);
stack.push(20);
System.out.println(stack.pop());
stack.push(30);
System.out.println(stack.pop());
System.out.println(stack.pop());
This code will produce the following output:
20
30
10
To encapsulate this functionality, you can create a new class called RoomTracker (or something similarly named to denote the action of tracking the previous rooms) and implement it as follows:
public class RoomTracker {
private final Deque<Integer> rooms = new ArrayDeque<>();
public void addRoomNumber(Integer roomNumber) {
rooms.push(roomNumber);
}
public Integer getPreviousRoomNumber() {
return rooms.pop();
}
}
In a similar fashion as before, you can use this code as follows:
RoomTracker tracker = new RoomTracker();
tracker.addRoomNumber(10);
tracker.addRoomNumber(20);
System.out.println(tracker.getPreviousRoomNumber());
tracker.addRoomNumber(30);
System.out.println(tracker.getPreviousRoomNumber());
System.out.println(tracker.getPreviousRoomNumber());
This will produce the following output:
20
30
10
If you need to track the direction in which you entered the room (so that you find if a player is going to a previous room), you can create a class called Room and store the randomly generated number and the direction in which the player entered:
public enum Direction {
TOP, RIGHT, BOTTOM, LEFT;
}
public class Room {
private final int number;
private final Direction enteredFrom;
public Room(int number, Direction enteredFrom) {
this.number = number;
this.enteredFrom = enteredFrom;
}
public int getNumber() {
return number;
}
public Direction getEnteredFrom() {
return enteredFrom;
}
}
You can then redefine RoomTracker in terms of Room:
public class RoomTracker {
private final Deque<Room> rooms = new ArrayDeque<>();
public void addRoom(Room room) {
rooms.push(room);
}
public Room getPreviousRoom() {
return rooms.pop();
}
}
You can then push Room objects onto the stack as the player travels from one room to the next. For example:
RoomTracker tracker = new RoomTracker();
tracker.push(new Room(10, Direction.LEFT); // Travel right into room 10
tracker.push(new Room(20, Direction.TOP); // Travel down into room 20

Run method on another thread android

i have an object that implements runnable. This object is my gameview, where the world of the game is processed.
Gameview is owned by another class: Game. Game is handling the UI for the gameView, so it is running on the ui-thread.
When the user touches something it is caught by the UI-thread. This is because if the user touches perhaps a skill-icon i need to pass data about what skill it was to the gameView.
My issue is that quite get:
java.util.ConcurrentModificationException
at java.util.Vector$Itr.checkForComodification(Vector.java:1193)
at java.util.Vector$Itr.next(Vector.java:1145)
at com.example.benjamin.dungeondweller.RenderSystem.render(RenderSystem.java:55)
at com.example.benjamin.dungeondweller.GameView.run(GameView.java:90)
at java.lang.Thread.run(Thread.java:764)
When touching the screen. I suspect it is because the method in GameView is still running on the UI thread, not the thread in the gameview.
To clarify here is the method in game (that is running on the UI-thread):
Where the third argument in gameView.touch would be the skill id (currently set to -1)
#Override
public boolean onTouchEvent(MotionEvent event) {
int x = (int)event.getX();
int y = (int)event.getY();
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
gameView.touch(x,y, -1);
break;
}
return true;
}
gamview.Touch:
public void touch(int screenX, int screenY, int skillId) {
int worldX = renderSystem.screenToWorldX(screenX);
int worldY = renderSystem.screenToWorldY(screenY);
renderSystem.clear();
if (map[worldX][worldY] != 1) {
ArrayList<Point> route = calculateRoute(new Point(0,0), new Point(worldX,worldY));
for (Point p : route) {
renderSystem.addSprite(R.drawable.guy, p.x, p.y);
}
}
(Currently only removing every sprite on the screen and adds new sprites)
When the crash occurs, the log refers to the run method in gameView:
#Override
public void run() {
while (running) {
if (!surfaceHolder.getSurface().isValid()) {
continue;
}
long startTime = System.currentTimeMillis();
int frameSkipped = 0;
//update();
Canvas canvas = surfaceHolder.lockCanvas();
if (canvas != null) {
canvas.drawARGB(255,65,65,65);
renderSystem.render(canvas); <---------- CRASH HERE
surfaceHolder.unlockCanvasAndPost(canvas);
}
long updateTime = System.currentTimeMillis() - startTime;
int sleepTime = (int)(FRAME_PERIOD - updateTime);
if (sleepTime > 0) {
try {
Message msg = new Message();
msg.obj = MAX_FPS;
msg.what = UPDATE_FPS;
handler.dispatchMessage(msg);
Thread.sleep(sleepTime);
} catch (InterruptedException e) {}
}
while (sleepTime < 0 && frameSkipped < MAX_FRAME_SKIPS) {
Message msg = new Message();
msg.obj = 1000 / updateTime;
msg.what = UPDATE_FPS;
handler.dispatchMessage(msg);
// update();
sleepTime+=FRAME_PERIOD;
frameSkipped++;
}
}
}
I think the issue is that the run method and touch method in GameView is running on different threads but i cant say for certain. How do i make it so that gameView.touch is running on the same thread as gameView.run?
Edit: formated code.
Edit: So to clarify further, i have one thread that's iterating the vector and one that tries to remove items in it. How do i make it so that the thread that removes items in the vector runs on the same thread as the one that iterates over it?

BooleanBinding and TimeLine

I've got a BooleanBinding, which looks like this:
public void initQueue(ObservableList<Player> players) {
queueIsFree = new BooleanBinding() {
{
players.forEach(
player -> bind(player.getRobot().animatingProperty));
}
#Override
protected boolean computeValue() {
Boolean bool = true;
for (Player p : players) {
if (p.getRobot().animatingProperty.get() == true) {
bool = false;
break;
}
}
return bool;
}
};
}
It is supposed to be true, when all of the animatingProperties of the Robots are false. As soon as one of them changes, this changeListener is called:
change = new ChangeListener<Boolean>() {
#Override
public void changed(ObservableValue<? extends Boolean> arg0,
Boolean oldValue, Boolean newValue) {
if (newValue.equals(true)) {
if (list.size() > 0) {
// plays the next animation, which, when finished, sets the animatingProperty back to false
nextAnimation();
} else {
stopQueue();
}
}
}
};
Problem: the valueChangedEvent fires so often, that i get a stackOverFlowError.
In order to animate, i use a TimeLine and an AnimationTimer, i suppose that this is the problem, yet i don't know how to solve it.
Edit: I know now, that the Problem is, that TimeLines are asynchronous, meaning, that they start and then the next line of code is executed, which means, that the booleanBinding, that i've created is useless.
I'll have to think of another way to play my animations one after another.

Positioning group in libgdx

BodyShadeImage= new Image(BodyShadeTexture);BodyShadeImage.setPosition(AssetsHelper.convertWidth(24),AssetsHelper.convertHeight(-68-73));Grp.addActor(BodyShadeImage);
ui.addActor(Grp);
public void AddLstr()
{
i++;
Action completeAction = new Action(){
public boolean act( float delta ) {
// System.out.println("i>>> "+i);
//if(i%3==0)
{
AddLstr();
}
return true;
}
};
Grp.addAction(Actions.sequence(Actions.moveBy(Grp.getX(),Grp.getY()+AssetsHelper.convertHeight(5),5f),completeAction));
//Grp1.addAction(Actions.moveBy(Grp.getX(),Grp.getY()+AssetsHelper.convertHeight(68),2f));
for(int i=0;i<PartsActual.length;i++)
{
PartsActual[i].addAction(Actions.moveBy(Grp.getX(),Grp.getY()+AssetsHelper.convertHeight(5),5f));
}
System.out.println("Grp.getY()"+Grp.getY());
}
Here is my code;for moving group to a fixed position.Actually i am moving group by 5pixel;but when i when i check group position.I am getting much deviation's. So group movement is not uniform.So can anyone help me to resolve this.

Debug Bluej for a Random Player

I'm trying to do a random method with BlueJ to play a random song of a playlist and then continue. My problem is that it just play one song and then stop. Here is my code. Hope someone can help me
https://gist.github.com/anonymous/9493432
My error is that all songs start simultaneously. Here is my code:
public void randomAllTracks(int index){
if(indexValid(index)) {
for(Track track : tracks) {
player.startPlaying(track.getFilename());
System.out.println("Now playing: " + track.getArtist() + " - " + track.getTitle());
System.out.println();
int randomTrack = (int)(Math.random() * tracks.size());
}
}
}
To get a random track that is always a valid index:
int randomTrack = (int)(Math.random() * tracks.size());
You can delete method randomTrack() because you don't need it.
You need some type of indication in class MusicPlayer to check whether the track is done. Here, this is represented by trackFinished. You can look at that variable as you play the song.
boolean trackFinished = true;
public void randomAllTracks(int index) {
while (true) {
if (trackFinished) {
playTrack((int)(Math.random() * tracks.size()));
trackFinished = false;
}
}
}
MusicPlayer code:
public class MusicPlayer
{
// The current player. It might be null.
private AdvancedPlayer player;
boolean finished = true;
//some code
public void startPlaying(final String filename)
{
try {
setupPlayer(filename);
Thread playerThread = new Thread() {
public void run()
{
try {
trackFinished = false;
player.play(5000);
}
catch(JavaLayerException e) {
reportProblem(filename);
}
finally {
killPlayer();
trackFinished = true;
}
}
};
playerThread.start();
}
catch (Exception ex) {
reportProblem(filename);
}
}
}

Categories