Every other rectangle detects the collison in my Java FX game - javafx

Okay so I have this little mock up game of clash royale and when I click to spawn a character and move him across the bridge on pane, I have a enemy on the bridge and my character stops as he should.
BUT, if I click to spawn my second character BEFORE he gets to enemy then the FIRST character moves through enemy and goes to tower.
Now, what I want to do is detect for every character, and they should all act the same. Not too sure what is going on here but I am needing a little assistance as this is the first game I've really made before.
private void createCharacter(CHARACTER choosenCharacter) {
gamePane.setOnMouseClicked(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
if (elixir > 4) {
character = new ImageView(choosenCharacter.getUrl());
healthbar = new Rectangle(50.0, 10.0, Color.BLUE);
character.setLayoutX(event.getSceneX() - 40);
character.setLayoutY(event.getSceneY() - 110);
healthbar.setLayoutX(event.getSceneX() - 40);
healthbar.setLayoutY(event.getSceneY() - 110);
System.out.println(event.getSceneX() + "\n" + event.getSceneY());
elixir = elixir - 6;
if (detectCollision()){
gameTimer.stop();
}
createGameLoop(character, healthbar);
gamePane.getChildren().add(character);
gamePane.getChildren().add(healthbar);
}
}
});
}
private void moveCharacter(ImageView character, Rectangle health) {
if (character.getLayoutX() > 180 && character.getLayoutX() < 450) {
character.setLayoutX(character.getLayoutX() - 2);
}
if (health.getLayoutX() > 180 && health.getLayoutX() < 450) {
health.setLayoutX(health.getLayoutX() - 2);
}
if (character.getLayoutX() <= 200 && character.getLayoutY() > 2) {
character.setLayoutY(character.getLayoutY() - 2);
}
if (health.getLayoutX() <= 200 && health.getLayoutY() > 2) {
health.setLayoutY(health.getLayoutY() - 2);
}
if (character.getLayoutX() < 700 && character.getLayoutX() >= 450) {
character.setLayoutX(character.getLayoutX() + 2);
}
if (health.getLayoutX() < 700 && health.getLayoutX() >= 450) {
health.setLayoutX(health.getLayoutX() + 2);
}
if (character.getLayoutX() >= 700 && character.getLayoutY() > 2) {
character.setLayoutY(character.getLayoutY() - 2);
}
if (health.getLayoutX() >= 700 && health.getLayoutY() > 2) {
health.setLayoutY(health.getLayoutY() - 2);
}
}
private void createGameLoop(ImageView character, Rectangle health) {
gameTimer = new AnimationTimer() {
#Override
public void handle(long now) {
if (detectCollision()){
gameTimer.stop();
}
moveCharacter(character, health);
}
};
gameTimer.start();
}
As you can see it's not the cleanest code but I need some way to detect each instance of my game character and I'm just not able to think of how to solve this little problem of mine. Any suggestions on how to handle something like this would be greatfully appreciated. Thanks!

Related

libgdx Trying to fix several problems, Orientation/Rotation of a 3D player using either WASD/Touchpad

Having hard time displacing and rotating a model
Trying to displace a model and rotate it,
in fact exporting it I had to make a first rotation and that seems to be were all the problem lies,
Would be pleased if someone could help a bit ^^
What I exactly would like to achieve is to be able to rotate and displace the payer with a single touchpad
Thats from the PlayerController:
public static Vector2 getMovementVector()
{
movementVector.set(touchPad.getKnobPercentX(),touchPad.getKnobPercentY());
return movementVector;
}
CharacterComponent is as follow:
public class CharacterComponent implements Component, Pool.Poolable{
public btConvexShape ghostShape;
public static btPairCachingGhostObject ghostObject;
public btKinematicCharacterController characterController;
public final Vector3 characterDirection = new Vector3();
public final Vector3 walkDirection = new Vector3();
#Override
public void reset() {
}}
PlayerModelComponent as follow:
public class PlayerModelComponent implements Component, Pool.Poolable {
public Model model;
public ModelInstance instance;
public PlayerModelComponent(Model model, float x, float y, float z) {
this.model = model;
this.instance = new ModelInstance(model, new Matrix4().setToTranslation(x, y, z));
}
#Override
public void reset() {
}}
That's from the Player movement system:
private void updateMovement(float delta) {
if (Gdx.app.getType() == Application.ApplicationType.Android || Gdx.app.getType() == Application.ApplicationType.iOS) {
deltaX = -PlayerController.getMovementVector().x * 0.75f; //Rotation Visuel X
deltaY = -PlayerController.getMovementVector().y * 0.75f; //Rotation Visuel X
}
tmp.set(0, 0, 1);
camera.rotate(camera.up, deltaX);
tmp.set(camera.direction).crs(camera.up).nor();
camera.direction.rotate(tmp, deltaY);
tmp.set(0, 0, 0);
characterComponent.characterDirection.set(0, 0, 0).rot(modelComponent.instance.transform).nor();
characterComponent.walkDirection.set(0, 0, 0);
//Move by MovePad
if (-PlayerController.getMovementVector().y < 0 || Gdx.input.isKeyPressed(Input.Keys.W)) {
characterComponent.walkDirection.set(0,0,-1);
characterComponent.characterDirection.set(0,0,-1);
//checkPlayerRot();
}
if (-PlayerController.getMovementVector().y > 0 || Gdx.input.isKeyPressed(Input.Keys.S)) {
characterComponent.walkDirection.set(0,0,1);
characterComponent.characterDirection.set(0,0,1);
}
if (-PlayerController.getMovementVector().x > 0 || Gdx.input.isKeyPressed(Input.Keys.A)) {
characterComponent.walkDirection.set(-1,0,0);
characterComponent.characterDirection.set(-1,0,0);
}
if (-PlayerController.getMovementVector().x < 0 || Gdx.input.isKeyPressed(Input.Keys.D)) {
characterComponent.walkDirection.set(1,0,0);
characterComponent.characterDirection.set(1,0,0);
}
//Move by Combo Input
if (Gdx.input.isKeyPressed(Input.Keys.W) && Gdx.input.isKeyPressed(Input.Keys.A)) {
characterComponent.walkDirection.set(-1,0,-1);
characterComponent.characterDirection.set(-1,0,-1);
}
if (Gdx.input.isKeyPressed(Input.Keys.W) && Gdx.input.isKeyPressed(Input.Keys.D)) {
characterComponent.walkDirection.set(1,0,-1);
characterComponent.characterDirection.set(1,0,-1);
}
if (Gdx.input.isKeyPressed(Input.Keys.S) && Gdx.input.isKeyPressed(Input.Keys.A)) {
characterComponent.walkDirection.set(-1,0,1);
characterComponent.characterDirection.set(-1,0,1);
}
if (Gdx.input.isKeyPressed(Input.Keys.S) && Gdx.input.isKeyPressed(Input.Keys.D)) {
characterComponent.walkDirection.set(1,0,1);
characterComponent.characterDirection.set(1,0,1);
}
if (Gdx.input.isKeyPressed(Input.Keys.SPACE)) {
//
}
// Mod Player Speed
if (Gdx.app.getType() == Application.ApplicationType.Android || Gdx.app.getType() == Application.ApplicationType.iOS) {
characterComponent.walkDirection.scl(0.5f * delta); //Vitesse Déplacement Personnage
}
if (Gdx.app.getType() == Application.ApplicationType.Desktop) {
characterComponent.walkDirection.scl(5f * delta); //Vitesse Déplacement Personnage
}
// Adding tmp to Char walk direction
characterComponent.characterController.setWalkDirection(characterComponent.walkDirection);
ghost = new Matrix4();
translation = new Vector3();
characterComponent.ghostObject.getWorldTransform(ghost);
ghost.getTranslation(translation);
modelComponent.instance.transform.set(
translation.x, translation.y, translation.z,
characterComponent.characterDirection.x, characterComponent.characterDirection.y, characterComponent.characterDirection.z, 0);
//BodyParts movement
hair.getComponent(PlayerModelComponent.class).instance.transform.set(translation.x, translation.y, translation.z, characterComponent.characterDirection.x, characterComponent.characterDirection.y, characterComponent.characterDirection.z, 0);
ear.getComponent(PlayerModelComponent.class).instance.transform.set(translation.x, translation.y, translation.z, characterComponent.characterDirection.x, characterComponent.characterDirection.y, characterComponent.characterDirection.z, 0);
mouth.getComponent(PlayerModelComponent.class).instance.transform.set(translation.x, translation.y, translation.z, characterComponent.characterDirection.x, characterComponent.characterDirection.y, characterComponent.characterDirection.z, 0);
scar.getComponent(PlayerModelComponent.class).instance.transform.set(translation.x, translation.y, translation.z, characterComponent.characterDirection.x, characterComponent.characterDirection.y, characterComponent.characterDirection.z, 0);
camera.position.set(translation.x, translation.y+3f,translation.z+15f);
//System.out.println("Camera pos("+ translation.x+"f," + translation.y+"f,"+ translation.z+"f);");
//System.out.println("Player Pos("+ camera.position.x+"f," + camera.position.y+"f,"+ camera.position.z+"f);");
x = translation.x;
y = translation.y;
z = translation.z;
camera.update(true);
}
While Idling..
While pressing W+A / S+A
While pressing W+D / S+D
Should go up, goes right / Same for the other one - should go down goes left
left or right on the touchpad does nothing here :/
Any clue here?
Would provide more if asked for,
thanks for any kind of help btw ;)

JavaFX Long pressButton

I'm currently building a Mobile app in JavaFx with the GluonMobile plugins and I try to find a way to know if the user just tap the button or if the button is pressed for over 2 second.
I try a couple of thing and I run into some problem.
The thing is I found this method on the web and he's my problem
First the code
button.addEventFilter(MouseEvent.ANY, new EventHandler<MouseEvent>() {
long startTime;
#Override
public void handle(MouseEvent event) {
if (event.getEventType().equals(MouseEvent.MOUSE_PRESSED)) {
startTime = System.currentTimeMillis();
} else if (event.getEventType().equals(MouseEvent.MOUSE_RELEASED)) {
if (System.currentTimeMillis() - startTime > 2 * 1000) {
System.out.println("Pressed for at least 2 seconds (" + (System.currentTimeMillis() - startTime) + " milliseconds)");
} else
System.out.println("Pressed for " + (System.currentTimeMillis() - startTime) + " milliseconds");
}
}
});
The problem that I have here is really weird.
When I click the button the method work.
If I click for over 2 sec it will printLn the good result.
BUT
If I click a second time on it it will print the PrintLn 2 times.
If I click a 3rd time, it will print the result 3 time...
So the problem is when I put a method (let's say a dialogBox) the box will show 3 times.
It's like if the program had a memory of how many time I click it and give me the result the number of time I click the button.
Can I "reset" the memory of the method?
Thanks.
Jc
EDIT
#FXML
public void buttonClick(ActionEvent actionEvent) {
btn1.addEventFilter(MouseEvent.ANY, new EventHandler<MouseEvent>() {
long startTime;
#Override
public void handle(MouseEvent event) {
if (event.getEventType().equals(MouseEvent.MOUSE_PRESSED)) {
startTime = System.currentTimeMillis();
} else if (event.getEventType().equals(MouseEvent.MOUSE_RELEASED)) {
if (System.currentTimeMillis() - startTime > 2 * 1000) {
System.out.println("Pressed for at least 2 seconds (" + (System.currentTimeMillis() - startTime) + " milliseconds)");
} else
System.out.println("Pressed for " + (System.currentTimeMillis() - startTime) + " milliseconds");
}
}
});
}

Recursive in java

public static void mystery(int num) {
System.out.print(num % 100);
if ((num / 100) != 0)
mystery(num / 100);
System.out.print(num % 100);
}
When I call mystery(456789), the result is 896745456789.
Why does it not stop at 89674545?
Let see for the first call. num % 100 is 89.
Your code:
print 89
.. do what ever
print 89
So it will print 89...whatever...89
It doesn't stop at 45 because it only return from the 3rd call, doesn't affect the first call.
As I guessed you wanted to reverse integer two by two digits. Well, method and logic isn't wrong but there is additional line. When number is devidedd by 100 and then it's given to recursion function, System.out.print(num % 100) is automatically done in that recursion, so printing it after recursion again causes additional numbers in answer.
public class Recursion {
public static void main(String[] args) {
mystery(456789);
}
public static void mystery(int num) {
System.out.print(num % 100);
if ((num / 100) != 0)
mystery(num / 100);
}
}
If you want the output as you specified in your question try the below code
public static void mystery(int num) {
System.out.print(num % 100);
if ((num / 100) != 0)
{
mystery(num / 100);
}
else
{
System.out.print(num);
}
}
Input: mystery(456789);
Output: 89674545

Items drawing relative to player when near edge of map

I have a tile engine and that's all working swell, my player walks around all good, I'm working on adding items, the player is always in the centre of the screen, until he gets close to the edges of the world then he starts going close to the edges.
When I draw items in the world, they draw fine, except when the player leaves the centre (at the edge of the world). I just can't wrap my head around how to fix this.
public static void Draw(SpriteBatch spriteBatch, World w, Item i, Player p, Point screenDimensions)
{
bool IsOnScreen = true;
float leftX = p.X - ((screenDimensions.X / 32) / 2);
float rightX = leftX + (screenDimensions.X / 32);
float topY = p.Y - ((screenDimensions.Y / 32) / 2);
float bottomY = topY + (screenDimensions.Y / 32);
if (i.x < leftX || i.x > rightX || i.y < topY || i.y > bottomY)
IsOnScreen = false;
if (IsOnScreen)
i.animation.Draw(spriteBatch, (int)Math.Floor((i.x - leftX) * 32), (int)Math.Floor((i.y - topY) * 32));
}
Its pretty self explainatory, the world is passed in to get the dimensions (w.worldDimensions.x for width, and .y for height), the item is used to get the i.x and i.y (location in game world, not on screen), the player for drawing it relative (contains .x and .y for location) and then the screenDimensions.
Well it does not look very clear to me. Are you using a camera class? If you use a camera class and use that to navigate your world this should never happen.
Here is a basic one i currently use for my project.
class Camera
{
float zoom;
public float Rotation { get; private set; }
public Vector2 Position { get; private set; }
Matrix transform;
int velocity = 60;
UserInput input;
public float Zoom
{
get { return zoom; }
set { zoom = value; if (zoom < 0.1f) zoom = 0.1f; } // Negative zoom will flip image
}
public Camera(UserInput input)
{
zoom = 1.0f;
Rotation = 0f;
Position = new Vector2(0, 0);
this.input = input;
}
public void MoveCam()
{
if (input.IsKeyHold(Keys.Up))
{
Position += new Vector2(0, -velocity);
}
if (input.IsKeyHold(Keys.Left))
{
Position += new Vector2(-velocity, 0);
}
if (input.IsKeyHold(Keys.Down))
{
Position += new Vector2(0, velocity);
}
if (input.IsKeyHold(Keys.Right))
{
Position += new Vector2(velocity, 0);
}
if (input.IsKeyHold(Keys.OemMinus))
{
Zoom -= .01f * Zoom;
}
else if (input.IsKeyHold(Keys.OemPlus))
{
Zoom += .01f * Zoom;
}
}
public void FollowCam(int xPos, int yPos)
{
Position = new Vector2(xPos * TileData.Width, yPos * TileData.Height);
}
public Matrix TransformMatrix(GraphicsDevice device)
{
transform = Matrix.CreateTranslation(new Vector3(-Position.X, -Position.Y, 0)) *
Matrix.CreateRotationX(MathHelper.ToRadians(Rotation)) *
Matrix.CreateRotationY(MathHelper.ToRadians(Rotation)) *
Matrix.CreateRotationZ(MathHelper.ToRadians(Rotation)) *
Matrix.CreateScale(new Vector3(zoom, zoom, 0)) *
Matrix.CreateTranslation(new Vector3(device.Viewport.Width * 0.5f, device.Viewport.Height * 0.5f, 0));
return transform;
}
}
Just instantiate the class like in main and use this in your draw method.
batch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, null, null, null, null, camera.TransformMatrix(graphicsDevice));
batch.End()
Draw everything in your world within this spritebatch and use a new basic to draw to screen cooridinates, like a gui/hud. You can use the camera move method to move it manually and the lock to lock it on any location (it follows if updated).
If you have large maps you might want to render only necessary tiles. I do it like this in my map class:
public void Draw(SpriteBatch batch, Vector2 camPosition, float camZoom, GraphicsDevice device)
{
float top = (camPosition.Y / TileData.Height) - ((device.Viewport.Height / 2) / TileData.Height + 1) / camZoom;
float bottom = (camPosition.Y / TileData.Height) + ((device.Viewport.Height / 2) / TileData.Height + 2) / camZoom;
float left = (camPosition.X / TileData.Width) - ((device.Viewport.Width / 2) / TileData.Width + 1) / camZoom;
float right = (camPosition.X / TileData.Width) + ((device.Viewport.Width / 2) / TileData.Width + 2) / camZoom;
for (int y = (int)top; y < (int)bottom; y++)
{
for (int x = (int)left; x < (int)right; x++)
{
if (y >= 0 && y < map.GetLength(1) && x >= 0 && x < map.GetLength(0))
{
batch.Draw(map[x, y].texture, new Rectangle(x * TileData.Width, y * TileData.Height, TileData.Width, TileData.Height), Color.White);
}
}
}
}
Here first i figure out which tiles to draw from each direction. Note the camZoom, you want more tiles to be drawn when zooming out. Then i use these "bounderies" in my for loops, the if statement makes sure i am not accessing tiles that dont exist (out of bounds).

Flex AS3: ProgressBar doesn't move

I am a little stuck and need some advice/help.
I have a progress bar:
<mx:ProgressBar id="appProgress" mode="manual" width="300" label="{appProgressMsg}" minimum="0" maximum="100"/>
I have two listener functions, one sets the progress, and one sets the appProgressMsg:
public function incProgress(e:TEvent):void {
var p:uint = Math.floor(e.data.number / e.data.total * 100);
trace("Setting Perc." + p);
appProgress.setProgress(p, 100);
}
public function setApplicationProgressStep(e:TEvent):void {
trace("Setting step:" + e.data);
appProgressMsg = e.data;
}
I want to reuse this progress bar alot. And not necessarily for ProgressEvents, but when going through steps.
For instance, I loop over a bunch of database inserts, and want to undate the progress etc.
Here is a sample:
public function updateDatabase(result:Object):void {
var total:int = 0;
var i:int = 0;
var r:SQLResult;
trace("updateDatabase called.");
for each (var table:XML in this.queries.elements("table")) {
var key:String = table.attribute("name");
if (result[key]) {
send(TEvent.UpdateApplicationProgressStep, "Updating " + key);
i = 1;
total = result[key].length;
for each (var row:Object in result[key]) {
//now, we need to see if we already have this record.
send(TEvent.UpdateApplicationProgress, { number:i, total: total } );
r = this.query("select * from " + key + " where server_id = '" + row.id + "'");
if (r.data == null) {
//there is no entry with this id, make one.
this.query(table.insert, row);
} else {
//it exists, so let's update.
this.update(key, row);
}
i++;
}
}
}
}
Everything works fine.
That is, the listener functions are called and I get trace output like:
updateDatabase called.
Setting step:Updating project
Setting Perc 25
Setting Perc 50
Setting Perc 75
Setting Perc 100
The issue is, only the very last percent and step is shown. that is, when it's all done, the progress bar jumps to 100% and shows the last step label.
Does anyone know why this is?
Thanks in advance for any help,
Jason
The new code, which works awesomely I might add:
public function updateDatabase(result:Object, eindex:int = 0, sindex:int = 0 ):void {
var total:int = 0;
var i:int = 0;
var j:int;
var r:SQLResult;
var table:XML;
var key:String;
var elems:XMLList = this.queries.elements("table");
var startTime:int = getTimer();
var row:Object;
for (i = eindex; i < elems.length(); i++) {
table = elems[i];
key = table.attribute("name");
if (!result[key])
continue;
total = result[key].length;
send(TEvent.UpdateApplicationProgressStep, "Updating " + key);
for (j = sindex; j < result[key].length; j++) {
if (getTimer() - startTime > 100) {
setTimeout(updateDatabase, 100, result, i, j);
send(TEvent.UpdateApplicationProgress, { number:j, total: total } );
return;
}
row = result[key][j];
r = this.query("select * from " + key + " where server_id = '" + row.id + "'");
if (r.data == null) {
//there is no entry with this id, make one.
this.query(table.insert, row,false);
} else {
//it exists, so let's update.
this.update(key, row,false);
}
}
send(TEvent.UpdateApplicationProgress, { number:1, total: 1 } );
}
}
Flash is single threaded. The display will not update until your function returns. For this reason, you should never have any code that runs for longer than about 100ms (1/10th of a second), otherwise the UI (or even the entire browser) will appear to be locked up.
The general solution is to split up your work over multiple frames, here is some pseudo-code:
function doWork(arg1:Obj, arg2:Obj, start:int=0) {
var startTime = getTimer(); // store starting time
for(i=start; i<length; i++) {
if(getTimer() - startTime > 100) { // see if we've been working too long
trace("Current progress: "+(i/length * 100)+"%");
updateProgress( i / length );
setTimeout(doWork, 100, arg1, arg2, i); // schedule more work to be done
return; // stop current loop
}
trace("Working on item "+i);
// processing here
}
trace("All work done");
}
doWork(data1, data2); // start the work
Your pseudo-code works for updating the progress bar however in my case my "work" was copying of files from DVD to the appStorageDirectory which seem to reintroduce the same issue that your work around resolved - the progress bar now does not update
Here is my hack of your solution
function doWork(arg1:int, arg2:int, start:int=0) {
var startTime = getTimer(); // store starting time
for(var i:int=start; i<arg2; i++) {
if(getTimer() - startTime > 100 ) { // see if we've been working too long
trace("Current progress: "+(i/arg2 * 100)+"%");
setTimeout(doWork, 100, i, arg2, i); // schedule more work to be done
return; // stop current loop
}
trace("Working on item "+i);
dispatchEvent(new progressMadeEvent("incrementChange",i,arg2))
var dir:String = copyRes[i].nativePath.toString().split(OSSep).pop()
copyRes[i].copyTo(appStore.resolvePath(dir)) // copies dir from DVD to appStorageDir
}
trace("All work done");
}

Resources