2

As this seems to be a recurring topic on 'the stack', I am going to reinforce my problem as something not covered. What has been covered is 2D tile collision for platform games etc., but with the way I have made my game, there are no tiles. I am also using no extra libraries, everything is written by my own hand.

What I have is bounding Rect's for every object in the game. So far there are only two object classes in use, Platform and Entity. Entity contains all the stuff for player movement etc. while Platform is for a solid non-moving platform.

Platform.java:

package com.toongames.game.objects;

import android.graphics.Color;
import android.graphics.Rect;

import com.toongames.framework.Graphics;

public class Platform {

    private int x, y;
    private int width, height;

    public Platform(int par1, int par2, int par3, int par4) {
        x = par1;
        y = par2;
        width = par3;
        height = par4;
    }

    public Rect getBounds() {
        return new Rect(x, y, x + width, y + height);
    }
}

Entity.java:

    package com.toongames.game.entity;

import android.graphics.Color;
import android.graphics.Point;
import android.graphics.Rect;

import com.toongames.framework.Graphics;
import com.toongames.framework.Image;

public class Entity {

    public final float GRAVITY = 0.1F;

    private String entityID;
    private Point pos;
    private int dx;
    private float vel;

    public Point desiredPos;
    public boolean onGround;

    public Entity(String par0String, int par1, int par2) {
        entityID = par0String;
        pos = new Point(par1, par2);

        desiredPos = pos;
        dx = 0;
        vel = 0;
    }

    public void update(float deltaTime) {
        vel = vel + (GRAVITY * deltaTime);

        pos.y += (vel * deltaTime);
        pos.x += dx;
    }

    public void setDx(int par1) {
        dx = par1;
    }

    public int getDx() {
        return dx;
    }

    public void setVelocity(int par1) {
        vel = par1;
    }

    public float getVelocity() {
        return vel;
    }

    public void setPos() {
        pos = desiredPos;
    }

    public Rect getBounds() {
        return new Rect(desiredPos.x, desiredPos.y, desiredPos.x + 80, desiredPos.y + 80);
    }
}

I have successfully made the player collide with things both up and down, but I cannot for the life of me manage to make the player collide right and left. Whenever I collide with a platform while moving left or right, I just jump to the top of the platform I collided with.

I know it has something to do with my logic, but I cannot figure out the correct logic to use.

ScreenGame.java:

    package com.toongames.game.screen;

// Imports here...

public class ScreenGame extends Screen {

    private Entity player;

    private Button left, right, jump;

    private Platform floor, p, p2, p3;
    private ArrayList<Platform> platforms;

    public ScreenGame(Game game) {
        super(game);

        player = new Entity("PLAYER", 300, 100, Assets.charRight);

        left = new Button(Assets.move_left, 10, 790 - Assets.move_left.getHeight(), Assets.move_left.getWidth(), Assets.move_left.getHeight());
        right = new Button(Assets.move_right, 20 + Assets.move_left.getWidth(), 790 - Assets.move_right.getHeight(), Assets.move_right.getWidth(), Assets.move_right.getHeight());
        jump = new Button(Assets.jump, 1270 - Assets.jump.getWidth(), 790 - Assets.jump.getHeight(), Assets.jump.getWidth(), Assets.jump.getHeight());

        floor = new Platform(0, 790, 1280, 80);
        p = new Platform(1280 - 500, 500, 400, 80);
        p2 = new Platform(0, 200, 400, 80);
        p3 = new Platform(400, 120, 200, 80);
        platforms = new ArrayList<Platform>();
        platforms.add(floor);
        platforms.add(p);
        platforms.add(p2);
        platforms.add(p3);
    }

    // An update method calls these
    public void updateMovement(float deltaTime) {
        List<TouchEvent> touchEvents = game.getInput().getTouchEvents();

        int len = touchEvents.size();
        for (int i = 0; i < len; i++) {
            TouchEvent event = touchEvents.get(i);
            if (event.type == TouchEvent.TOUCH_DOWN) {
                if (inBounds(left.getBounds(), event)) {
                    player.setDx((int) -(deltaTime * 1.5F));
                } else if (inBounds(right.getBounds(), event)) {
                    player.setDx((int) deltaTime * 2);
                } else if (inBounds(jump.getBounds(), event)) {
                    if (player.onGround) {
                        player.setVelocity(-8);
                    }
                }
            } else if (event.type == TouchEvent.TOUCH_DRAGGED) {
                if (inBounds(left.getBounds(), event)) {
                    player.setDx((int) -deltaTime * 2);
                } else if (inBounds(right.getBounds(), event)) {
                    player.setDx((int) deltaTime * 2);
                } else if (inBounds(jump.getBounds(), event)) {
                    if (player.onGround) {
                        player.setVelocity(-8);
                    }
                } else {
                    player.setDx(0);
                    player.jumpCounter = 0;
                }
            } else if (event.type == TouchEvent.TOUCH_UP) {
                player.setDx(0);
                player.jumpCounter = 0;
            }
        }
    }

    // An update method calls these
    public void updateGameObjects(float deltaTime) {
        for (Platform p : platforms)
            p.update();

        player.update(deltaTime);
    }

    // An update method calls these
    public void checkCollisions() {
        Rect playerRect = player.getBounds();

        for (Platform p : platforms) {
            Rect pRect = p.getBounds();

            if (Rect.intersects(playerRect, pRect)) {
                Rect intersection = playerRect;
                intersection.intersect(pRect);

                if (player.getVelocity() != player.GRAVITY) {
                    int resolutionHeight;

                    if (player.getVelocity() < player.GRAVITY)
                        resolutionHeight = intersection.height();
                    else {
                        resolutionHeight = -intersection.height();
                        player.onGround = true;
                    }

                    player.setVelocity(0);

                    player.desiredPos = new Point(player.desiredPos.x, player.desiredPos.y + resolutionHeight);
                }
            }
        }

        player.setPos();
    }
}

As an extra note, I have cut out some of the unnecessary code to do with images for the entity and entity health etc.. Also I have cut out empty methods and stuff like that that have no relevance what so ever.

[EDIT] Cut out most of the drawing code and imports. All the absolutely necessary stuff is there now.

Kwibble
  • 45
  • 7
  • @portforwardpodcast I started looking into some physics engines, but then realised that I would have to build an entirely new framework, and I would also have to use most of their processes etc., but all I needed was gravity. So I just made gravity and am now adding collision detection. Surely there is nothing wrong with this? – Kwibble Dec 12 '13 at 01:51
  • Have you looked into the JST Topology Suite? http://tsusiatsoftware.net/jts/main.html If you want a demo of what it can do check this out: http://bl.ocks.org/christophermanning/4450188 – benathon Dec 12 '13 at 02:06
  • @portforwardpodcast I'd appreciate it if you could please help me with my original question instead of giving me this other stuff... It is good stuff, no doubt about it, but its not what I am wanting. I have given my reasons as to why I am using my own physics, and so I'd appreciate it if you would help me with it. Thanks – Kwibble Dec 12 '13 at 02:33
  • This post has too much code for me to effictivly give you an answer. Pairing down your code even further can often lead to an answer. – benathon Dec 12 '13 at 10:37
  • 1
    @portforwardpodcast I will try to do so, thanks for the tip. – Kwibble Dec 13 '13 at 04:56

1 Answers1

0
player.desiredPos = new Point(player.desiredPos.x, player.desiredPos.y + resolutionHeight);

isn't this "move above, never right/left?"

I think your Rect.intersects method should return one of { NONE, LEFT, RIGHT, UP, DOWN } indicating in which direction the collision occured. So you can react to the collision in the right direction...

Exceptyon
  • 1,584
  • 16
  • 23
  • I had a collision system like this to start with, but that was BEFORE I added gravity. Once I added gravity, every collision was now two collisions, a down collision and a whatever else collision. So then the collision never worked as intended. Also, I was reading a tutorial that used a tilemap, and even though it was a tile map, it still had the right collision ideas. If you are falling, then you want to be doing a collision fix of left right because you still want to fall down. Same with moving left/right on a platform, fix by moving up. (to be continued) – Kwibble Dec 13 '13 at 04:57
  • (continues) But that still doesn't give me a way to fix moving into the side of a wall while NOT falling. Thats part of the problem I am having... Thanks for the answer though :D – Kwibble Dec 13 '13 at 05:00