i'm using RayCastCallback interface ıf LibGDX. I couldn't find a way to get closest point from start of the ray. It returns random fixtures that hit by the ray. How can i get the closest collision point between ray and the fixture?
Sounds like you've got most of the code there, since you're getting fixtures back from your raycast. You'll just need to loop through all fixtures hit by the raycast and remember the closest one. Something like:
public class SomeClass {
private World world;
private Vector2 fromPoint;
private Vector2 toPoint;
private Vector2 collisionPoint = new Vector2();
float closestFraction = 1.0f;
// ... rest of code ...
private void calculateCollisionPoint() {
RayCastCallback callback = new RayCastCallback() {
#Override
public float reportRayFixture(Fixture fixture, Vector2 point, Vector2 normal, float fraction) {
if ( fraction < SomeClass.this.closestFraction ) {
SomeClass.this.closestFraction = fraction;
SomeClass.this.collisionPoint.set(point);
}
return 1;
}
};
world.rayCast(callback, fromPoint, toPoint);
}
}
Related
I want an actor to move with velocity (speed) and acceleration to specified coordinate. Yes I know MoveTo action can move an actor to the coordinate that we want. But it doesn't move an actor with velocity and acceleration. It just calculates duration so there is no velocity no acceleration if we move actor using MoveTo action. How can we set acceleration and velocity for different destination coordinates to move actor ?
For example there can be a class like following but I don't know how it to be
class MyActor extends Actor {
private Vector2 destination;
public void setVelocity(float velocity) {
... codes
..
.
}
public void setAcceleration(float acc) {
... codes
..
.
}
public void move(float delta) {
... codes
..
.
}
public void setDestination(Vector2 destination) {
this.destination = destination;
... codes
..
.
}
public void act(float delta) {
super.act(delta);
move(delta);
}
}
MyActor actor = new MyActor();
actor.setVelocity(5);
actor.setAcceleration(0.2f);
actor.setDestination(new Vector2(250, 300));
You can divide distance by velocity to get duration.
You might want to remove existing move actions when adding a new one so they don't start piling up. I put a method for that below. Not sure if you could simplify it by simply removing the action from within the for loop. That could possibly mess up the iterator.
class MyActor extends Actor {
public float velocity = 20f; //arbitrary initial value
private final Vector2 tmpV = new Vector2(); //for calculations
public void setDestination (float x, float y){
clearMoveAction(); // If you want to interrupt any existing motion
float distance = tmpV.set(x - getX(), y - getY()).len();
addAction(Actions.moveTo(x, y, distance / velocity));
}
void clearMoveAction(){
Array<Action> actions = getActions();
Action moveAction = null;
for (Action action : actions)
if (action instanceof MoveToAction){
moveAction = action;
break;
}
if (moveAction != null)
removeAction(moveAction);
}
}
I have a gameObject called BounceBack that is supposed to bounce the ball back far away when they collide together.
public class BounceBack : MonoBehaviour
{
public GameObject Player;
public float force;
private void OnCollisionEnter(Collision collision)
{
if (collision.gameObject.CompareTag(Player.tag))
{
Player.GetComponent<PlayerController>().ForceBack(force);
}
}
}
The ball Player (ball) script:
public class PlayerController : MonoBehaviour
{
public int acceleration;
public int speedLimit;
public int sideSpeed;
public Text countText;
public Text winText;
public GameObject pickUp;
public GameObject finishLine;
//internal void ForceBack() //Not sure what it does and why it's there.
//{
// throw new NotImplementedException();
//}
private int count;
private Rigidbody rb;
// Start is called before the first frame update
void Start()
{
rb = GetComponent<Rigidbody>();
SetCount();
}
// Update is called once per frame
void FixedUpdate()
{
float moveHorizontal = Input.GetAxis("Horizontal") * sideSpeed * rb.velocity.magnitude / acceleration;
//float moveVertical = Input.GetAxis("Vertical") * acceleration;
if (rb.velocity.magnitude <= speedLimit)
{
rb.AddForce(0.0f, 0.0f, acceleration); // add vertical force
}
rb.AddForce(moveHorizontal, 0.0f, 0.0f); // add horizontal force
}
private void OnTriggerEnter(Collider other)
{
if (other.gameObject.CompareTag(pickUp.tag))
{
other.GetComponent<Rotate>().Disapear();
count++;
SetCount();
}
if (other.gameObject.CompareTag(finishLine.tag))
{
acceleration = 0;
sideSpeed = 0;
finishLine.GetComponent<GameEnd>().FadeOut();
if (count >= 2)
{
winText.GetComponent<WinTextFadeIn>().FadeIn("Vous avez remporté la partie!");
}
else
{
winText.GetComponent<WinTextFadeIn>().FadeIn("Vous avez perdu. Réesayer?");
}
}
}
private void SetCount()
{
countText.text = "Count : " + count.ToString();
}
public void ForceBack(float force)
{
Rigidbody rb = GetComponent<Rigidbody>();
rb.AddForce(0.0f, 0.0f, -force, ForceMode.VelocityChange);
Debug.Log("Pass");
}
}
The AddForce function does not do anything. I tried with setActive(false) and it's not working either. The only thing that works is Debug.Log(). I'm not sure if the speedlimit and acceleration are interfering with the function.
EDIT: I'm not sure if the problem is from Unity but I can't access any variable of the class from the forceBack function inside the class.
EDIT2: I also tried to call the AddForce function directly in the Bounce Back script but it's not working either.
Player.GetComponent<Rigidbody>().AddForce(0.0f, 0.0f, -force, ForceMode.VelocityChange);
Player (Ball) Screenshot
Bounce Back Screenshot
So, a couple things:
1.) The physics system should already cause the ball to bounce if you've set up the colliders and rigidbodies properly. You should only need to do something like this if the ball should gain momentum when it bounces, which is unlikely. You should post screenshots of their inspectors if this answer doesn't help.
2.) On your rb.AddForce() call, you're applying a force in world-space, which may be the wrong direction to bounce. If you know the ball is oriented the way it's moving, then you can call AddRelativeForce with the same parameters. If the ball's orientation is not controlled, then you need to calculate the correct world-space direction to use before applying the force.
3.) Finally, just to confirm, the objects with BounceBack attached do have a non-zero value in the 'force' parameter in the inspector, right?
I am building a flappy bird style side scroller game and currently implementing collectible items for the main sprite to collect as it flies. I am not moving the main sprite but moving the background using ParallaxEffect and intend to move the collectibles (called orbs) towards the main sprite (bird). The Orbs are rendered in random positions but the position is not changed even after the update method is called.
Here is my CollectibleOrbs.java
public class CollectibleOrbs {
private static final int ORB_COUNT = 10;
private Array<Orb> orbs;
private Orb orb;
public CollectibleOrbs(){
orbs = new Array<Orb>();
for(int i=0;i<ORB_COUNT; i++) {
orb = new Orb();
orbs.add(orb);
}
}
public void update(float delta){
for(Orb orb: orbs){
orb.update(delta);
}
}
public void render(SpriteBatch sb){
for(Orb orb:orbs){
orb.draw(sb);
}
}
private class Orb{
private ParticleEffect effect;
private Vector2 position;
private Random rand;
public Orb(){
effect = new ParticleEffect();
rand = new Random();
position = new Vector2(rand.nextInt(Gdx.graphics.getWidth()),rand.nextInt(Gdx.graphics.getHeight()));
effect.load(Gdx.files.internal("particle/orbred.p"),
Gdx.files.internal("particle"));
effect.setPosition(position.x,position.y);
}
public void draw(SpriteBatch sb){
effect.draw(sb,Gdx.graphics.getDeltaTime());
}
public void update(float dt){
if(position.x< 10){
position.x = rand.nextInt(Gdx.graphics.getWidth());
position.y = rand.nextInt(Gdx.graphics.getHeight());
}
else
{
position.x-= 100*dt;
}
}
}
}
The orbs are rendered but they are not moving whereas the bird animation and the parallax background does:
I am calling the update method of CollectibleOrb class in the update of my game state and respectively for the render method while passing required parameters. How do to make sure the orbs move on the game screen?
The problem is that position is just unrelated to effect vector. Changing just position won't change effect's position. One way to solve it:
public void update(float dt){
if(position.x< 10){
position.x = rand.nextInt(Gdx.graphics.getWidth());
position.y = rand.nextInt(Gdx.graphics.getHeight());
}
else
{
position.x-= 100*dt;
}
// you should update ParticleEffect position too, just like you did in the constructor
effect.setPosition(position.x, position.y);
}
I am making a game in libgdx, where you shoot aliens with bullets. I have 2 ArrayLists of objects and would like to check if any of objects in bulletArrayList is colliding with any object from alienArrayList. What is the best way to do that? I was thinking of contactListener.
In the screen class I am generating objects like this:
public class PlayScreen implements Screen, InputProcessor,ContactListener {
public ArrayList<Alien> alienArrayList = new ArrayList<Alien>();
public ArrayList<Bullet> bulletArrayList = new ArrayList<Bullet>();
public void generateAlien() {
alien = new Alien();
alienArrayList.add(alien);
}
public void shootBullet(float x, float y) {
//send x,y moving coordiantes
bullet = new Bullet(x,y);
bulletArrayList.add(bullet);
}
}
In object class I have Rectangle box which i am moving like this:
public class Alien {
public Alien() {
bound = new Rectangle( x, y, alienRegion.getRegionWidth(), alienRegion.getRegionHeight());
}
public void update(float delta) {
bound.y -= speed * delta;
}
public void render(SpriteBatch batch, float delta) {
update(delta);
elapsedTime += Gdx.graphics.getDeltaTime();
alienRegion = (TextureRegion) alien.getKeyFrame(elapsedTime, true);
batch.draw(alienRegion, getBound().x, getBound().y);
}
}
Because you are using Rectangles in your Alien class, we can use a class called Intersector which has static methods to check for collision detection.
for(Alien alien1: alienArrayList) {
for(Alien alien2 : bulletArrayList) {
if(Intersector.overlaps(alien1.rect, alien2.rect)) {
// Collision code
}
}
}
First, we iterate through the two lists using a nested special for loop. Then we pass two Rectangles to the Intersector.overlaps(rect1, rect2). This is a static method defined in the Intersector class which will return true if the rectangles are overlapping.
Also, this code can go straight into your render method.
This code is not the most optimized because it will check 2 rects twice however, I will leave the optimization to you.
I hope that this answer was helpful and if you have any further questions please feel free to post a comment below.
public class gameMain implements Screen {
final main game;
SpriteBatch batch;
Texture img;
private Texture alexTexture;
private Rectangle alex;
private Texture cTex;
private Texture dropper;
private Texture ender;
private Texture partsImg;
private Texture toy;
private OrthographicCamera camera;
private Array<Rectangle> part; // ******
private long lastDropTime;
private int beltSpeed = 100; // ******
//Score Keeper
private int score;
private String scoreName;
//basically a create method
public gameMain(final main gam){
this.game = gam;
// load images into memory
dropper = new Texture("android/assets/dropper.png");
ender = new Texture("android/assets/endOfBelt.png");
partsImg = new Texture("android/assets/unmadeToyParts.png");
toy = new Texture("android/assets/toymade.png");
cTex = new Texture("android/assets/conveyerBeltBackground.png");
alexTexture = new Texture(Gdx.files.internal("android/assets/alexAlpha2.png"));
// set the game window resolution
camera = new OrthographicCamera();
camera.setToOrtho(false, 1080,720);
// Alex's position / hitbox
alex = new Rectangle();
alex.x = 250;
alex.y = 150;
alex.width = 126;
alex.height = 75;
// part stuff
part = new Array<Rectangle>();
spawnPart();
// score handler
score = 0;
scoreName = "Toys Made: ";
}
private void spawnPart(){ // *******
Rectangle parts = new Rectangle();
parts.x = 0;
parts.y = 210;
parts.width = 52;
parts.height = 60;
part.add(parts);
lastDropTime = TimeUtils.nanoTime();
} //********
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
camera.update();
// load alex sprite
game.batch.setProjectionMatrix(camera.combined);
// begin drawing to screen
game.batch.begin();
batch.draw(cTex, -5, 200); // draw conveyer background
batch.draw(dropper, 0, 210); // draw the dropper
batch.draw(ender, 600, 200); // draw the ender
game.batch.draw(alexTexture, alex.x, alex.y); // draw alex
for(Rectangle parts: part){
game.batch.draw(partsImg, parts.x, parts.y); // draw part
}
game.font.draw(game.batch, scoreName, 25, 100); // draw scoreboard
game.batch.end(); // end drawing to screen
//******************************************************************************
//HERE IS WHERE I AM TRYING TO PUT IT
part.x += beltspeed;
if (part.rectangle overlaps ender.rectangle){
despawn part;
}
//******************************************************************************
}
#Override
public void show() {
}
#Override
public void hide() {
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void resize(int width, int height) {
}
#Override
public void dispose() {
}
}
Hello I am very new to LibGDX, and after doing some research I decided to make a game where you are a factory worker named Alex and you build toys. I will gladly take any feedback you have to make my code more orginized or work better. I highlighted everything I believe to be relevant to my question with some asterisks.
But my question is: How do you make a 'rectangle' such as my 'part' move on its own. I added a beltspeed and a spawn zone, and once the hitbox for it goes over the 'ender' hitbox I would like to despawn it.
Also I haven't gotten this far yet, but when the 'part' hitbox passes over 'Alex' hitbox I would like a little minigame to appear where you have to press up, down, left, right (randomly) to build the toy. If you have any suggestions on how I should handle that, I would be very appreciative.
"C:\Program Files\Java\jdk1.7.0_79\jre\bin\java" -Didea.launcher.port=7532 "-Didea.launcher.bin.path=C:\Program Files (x86)\JetBrains\IntelliJ IDEA Community Edition 2016.1.1\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.7.0_79\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\jce.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\jfxrt.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\resources.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\rt.jar;C:\Users\RAFiredog\Desktop\Intellij\AlexTheTemp\out\production\desktop;C:\Users\RAFiredog\Desktop\Intellij\AlexTheTemp\out\production\core;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\com.badlogicgames.gdx\gdx\1.9.2\e641cb91bec06bc64d9ddf7a7d7062caceec73cd\gdx-1.9.2.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\com.badlogicgames.gdx\gdx-box2d\1.9.2\b78eaa90aaaf7830e6dffff587ea6e859c2787b2\gdx-box2d-1.9.2.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\com.badlogicgames.gdx\gdx-freetype\1.9.2\3609253d14edb1b3ca5aacff4e06989edde75be4\gdx-freetype-1.9.2.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\com.badlogicgames.gdx\gdx-backend-lwjgl\1.9.2\d710a8704ed584ec2ba9ca52e3a6a5885dd759cc\gdx-backend-lwjgl-1.9.2.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\com.badlogicgames.gdx\gdx-platform\1.9.2\dde4cf7e9ce61c24042f512203aed87657496639\gdx-platform-1.9.2-natives-desktop.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\com.badlogicgames.gdx\gdx-box2d-platform\1.9.2\497cbfbf81e7e8b1e8433b19291c5af4bbc2ec66\gdx-box2d-platform-1.9.2-natives-desktop.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\com.badlogicgames.gdx\gdx-tools\1.9.2\37d8e3009ae0febdf93717b21980c67c8cadac07\gdx-tools-1.9.2.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\com.badlogicgames.gdx\gdx-freetype-platform\1.9.2\1e1afb0b6c9e8aeb7d495cb8f55c353d3da58cf0\gdx-freetype-platform-1.9.2-natives-desktop.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\org.lwjgl.lwjgl\lwjgl\2.9.2\a9d80fe5935c7a9149f6584d9777cfd471f65489\lwjgl-2.9.2.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\org.lwjgl.lwjgl\lwjgl_util\2.9.2\4b9e37300a87799856e0bd15ed81663cdb6b0947\lwjgl_util-2.9.2.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\com.badlogicgames.jlayer\jlayer\1.0.1-gdx\7cca83cec5c1b2f011362f4d85aabd71a73b049d\jlayer-1.0.1-gdx.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\org.jcraft\jorbis\0.0.17\8872d22b293e8f5d7d56ff92be966e6dc28ebdc6\jorbis-0.0.17.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\com.badlogicgames.gdx\gdx-backend-headless\1.9.2\813e6020de85cd831f02cb5e9060fd7ea8cb208e\gdx-backend-headless-1.9.2.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\org.lwjgl.lwjgl\lwjgl-platform\2.9.2\510c7d317f5e9e700b9cfaac5fd38bdebf0702e0\lwjgl-platform-2.9.2-natives-windows.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\org.lwjgl.lwjgl\lwjgl-platform\2.9.2\d276cdf61fe2b516c7b7f4aa1b8dea91dbdc8d56\lwjgl-platform-2.9.2-natives-linux.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\org.lwjgl.lwjgl\lwjgl-platform\2.9.2\d55b46b40b40249d627a83a7f7f22649709d70c3\lwjgl-platform-2.9.2-natives-osx.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\net.java.jinput\jinput\2.0.5\39c7796b469a600f72380316f6b1f11db6c2c7c4\jinput-2.0.5.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\net.java.jutils\jutils\1.0.0\e12fe1fda814bd348c1579329c86943d2cd3c6a6\jutils-1.0.0.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\net.java.jinput\jinput-platform\2.0.5\7ff832a6eb9ab6a767f1ade2b548092d0fa64795\jinput-platform-2.0.5-natives-linux.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\net.java.jinput\jinput-platform\2.0.5\385ee093e01f587f30ee1c8a2ee7d408fd732e16\jinput-platform-2.0.5-natives-windows.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\net.java.jinput\jinput-platform\2.0.5\53f9c919f34d2ca9de8c51fc4e1e8282029a9232\jinput-platform-2.0.5-natives-osx.jar;C:\Program Files (x86)\JetBrains\IntelliJ IDEA Community Edition 2016.1.1\lib\idea_rt.jar" com.intellij.rt.execution.application.AppMain com.rafiredog.game.desktop.DesktopLauncher
Exception in thread "LWJGL Application" java.lang.NullPointerException
at com.rafiredog.game.gameMain.render(gameMain.java:97)
at com.badlogic.gdx.Game.render(Game.java:46)
at com.rafiredog.game.main.render(main.java:45)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication.mainLoop(LwjglApplication.java:223)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication$1.run(LwjglApplication.java:124)
Process finished with exit code 0
Lastly, I am now getting this error. I moved some code around near the 'batch.draw'. However that might not be the cause of the error? I am a little lost right now. But I will gladly screenshot what I have of the game now once the errors are resolved.
Thank you for any insight you have on fixing up this game.
You need to do game updates and then rendering on each cycle of the game loop. The game update part of your code can iterate through your objects to do stuff to them.
For example, your render method would look like this. You need to explicitly use an Iterator for your for loop because you otherwise could not remove items from the list while iterating.
#Override
public void render(float delta) {
//Update game
Iterator<Rectangle> iterator = parts.iterator();
while (iterator.hasNext()){
Rectangle part = iterator.next();
part.x += beltSpeed * delta; //distance = speed * time
if (part.rectangle.overlaps(ender.rectangle)){
iterator.remove(); //removes rectangle from the list
}
}
//This is also where you would update movement for anything else,
//such as a character jumping, or counting down a timer and spawning
//something when it reaches zero, for example.
//Draw everything
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
camera.update();
game.batch.setProjectionMatrix(camera.combined);
game.batch.begin();
//...
game.batch.end();
}
If you spawn and "despawn" a lot of objects, you will probably need to use pooling to avoid stutters from memory deallocation. You can do this by replacing new Rectangle() with Pools.obtain(Rectangle.class) and adding the line Pools.free(part) right after iterator.remove().
I also noticed you have counter-intuitive usage of the words "part" and "parts" by swapping plural and singular. Make sure that doesn't trip you up.
As for your NullPointerException, read here.
Piggy backing onto Tenfour04's answer and attempting to answer your question in the comments. I'd suggest looking at this link: https://github.com/libgdx/libgdx/wiki/The-life-cycle