From 954e79bcd221966171e68b5c8599704cc6bdef06 Mon Sep 17 00:00:00 2001 From: Robert Wolfinger Date: Mon, 12 Oct 2015 06:51:25 +0200 Subject: [PATCH] Working on collision --- resources/maps/CollisionTest.tmx | 2 +- src/de/dungeonrunner/Animation.java | 4 +- src/de/dungeonrunner/Application.java | 37 +----- src/de/dungeonrunner/GameEntity.java | 4 - src/de/dungeonrunner/GameWorld.java | 6 +- src/de/dungeonrunner/PlayerEntity.java | 66 ++++++----- src/de/dungeonrunner/SceneNode.java | 149 +++++++++++++++++++++---- src/de/dungeonrunner/SpriteNode.java | 5 + 8 files changed, 178 insertions(+), 95 deletions(-) diff --git a/resources/maps/CollisionTest.tmx b/resources/maps/CollisionTest.tmx index f6c96b8..ab68c99 100644 --- a/resources/maps/CollisionTest.tmx +++ b/resources/maps/CollisionTest.tmx @@ -20,7 +20,7 @@ - eJxjYCAOKBKhRnWEq1PBwQap0wRiZQJYF4gB6dsD5w== + eJxjYCAOKBOpZiSrU8HBViYBAwDrAwPX diff --git a/src/de/dungeonrunner/Animation.java b/src/de/dungeonrunner/Animation.java index 4757982..3860668 100644 --- a/src/de/dungeonrunner/Animation.java +++ b/src/de/dungeonrunner/Animation.java @@ -60,8 +60,8 @@ public void update(Time dt) { mSprite.setTextureRect(textureRect); } - - public FloatRect getGlobalBounds(){ + + public FloatRect getGlobalBounds() { return mSprite.getGlobalBounds(); } diff --git a/src/de/dungeonrunner/Application.java b/src/de/dungeonrunner/Application.java index 43aae5b..9b62c70 100644 --- a/src/de/dungeonrunner/Application.java +++ b/src/de/dungeonrunner/Application.java @@ -17,7 +17,7 @@ public Application() { mRenderWindow = new RenderWindow(); mRenderWindow.create(new VideoMode(800, 480, 32), "DungeonRunner"); mRenderWindow.setFramerateLimit(30); - + mGameWorld = new GameWorld(mRenderWindow); mClock = new Clock(); @@ -60,40 +60,5 @@ public static void main(String[] args) { Application application = new Application(); application.run(); - // GameWorld world = new GameWorld(window); - -// while (window.isOpen()) { -// window.clear(); -// // world.draw(); -// window.display(); -// } - - // while (window.isOpen()) { - // for (Event event : window.pollEvents()) { - // - // switch (event.type) { - // case CLOSED: - // window.close(); - // break; - // case RESIZED: - // view = new View(new Vector2f(window.getSize().x / 2, - // window.getSize().y / 2), - // new Vector2f(window.getSize())); - // window.setView(view); - // break; - // case KEY_PRESSED: - // view.move(new Vector2f(10, 0)); - // window.setView(view); - // default: - // break; - // } - // } - // - // window.clear(); - // - // window.draw(playerEntity); - // window.display(); - // } - } } diff --git a/src/de/dungeonrunner/GameEntity.java b/src/de/dungeonrunner/GameEntity.java index 8486737..3278375 100644 --- a/src/de/dungeonrunner/GameEntity.java +++ b/src/de/dungeonrunner/GameEntity.java @@ -1,18 +1,14 @@ package de.dungeonrunner; -import org.jsfml.graphics.IntRect; import org.jsfml.system.Time; import org.jsfml.system.Vector2f; public abstract class GameEntity extends SceneNode { private Vector2f mVelocity; - private Vector2f mAfterCollVelocity; - private IntRect mCollisionRectangle; public GameEntity() { mVelocity = Vector2f.ZERO; - mAfterCollVelocity = mVelocity; } public void setVelocity(Vector2f velocity) { diff --git a/src/de/dungeonrunner/GameWorld.java b/src/de/dungeonrunner/GameWorld.java index 9e85bcb..8546839 100644 --- a/src/de/dungeonrunner/GameWorld.java +++ b/src/de/dungeonrunner/GameWorld.java @@ -2,6 +2,8 @@ import java.awt.Rectangle; import java.util.HashMap; +import java.util.HashSet; +import java.util.Set; import org.jsfml.graphics.FloatRect; import org.jsfml.graphics.RenderWindow; @@ -10,6 +12,7 @@ import org.jsfml.system.Time; import org.jsfml.system.Vector2f; +import de.dungeonrunner.SceneNode.CollisionPair; import de.dungeonrunner.TextureHolder.TextureID; import tiled.core.Map; import tiled.core.Tile; @@ -44,7 +47,6 @@ public GameWorld(RenderWindow window) { loadMap(); loadTextures(); buildScene(); - } private void loadTextures() { @@ -126,5 +128,7 @@ public void draw() { public void update(Time dt) { mSceneGraph.update(dt); + Set collisionPairs = new HashSet<>(); + mSceneGraph.checkSceneCollision(mSceneGraph, collisionPairs); } } diff --git a/src/de/dungeonrunner/PlayerEntity.java b/src/de/dungeonrunner/PlayerEntity.java index 500ea8d..a720dcf 100644 --- a/src/de/dungeonrunner/PlayerEntity.java +++ b/src/de/dungeonrunner/PlayerEntity.java @@ -1,10 +1,6 @@ package de.dungeonrunner; -import java.util.List; -import java.util.Properties; - import org.jsfml.graphics.FloatRect; -import org.jsfml.graphics.IntRect; import org.jsfml.graphics.RenderStates; import org.jsfml.graphics.RenderTarget; import org.jsfml.system.Time; @@ -12,55 +8,63 @@ import org.jsfml.system.Vector2i; import de.dungeonrunner.TextureHolder.TextureID; -import tiled.core.Map; -import tiled.core.Tile; public class PlayerEntity extends GameEntity { private Animation mIdleAnimation; public PlayerEntity(TextureID textureID) { + mProperties.setProperty("BlockVolume", "true"); mIdleAnimation = new Animation(textureID); mIdleAnimation.setDuration(Time.getMilliseconds(900)); mIdleAnimation.setRepeat(true); mIdleAnimation.setNumFrames(6); mIdleAnimation.setFrameSize(new Vector2i(128, 128)); - setVelocity(new Vector2f(100f, 0)); - - Map map = TmxMapLoader.getMap(); - System.out.println(map.getBounds()); -// checkCollision(); + setPosition(20f, 0f); + mIdleAnimation.setPosition(getPosition()); + setVelocity(new Vector2f(10f, 0f)); } @Override protected void drawCurrent(RenderTarget target, RenderStates states) { mIdleAnimation.draw(target, states); + super.drawCurrent(target, states); } @Override protected void updateCurrent(Time dt) { - super.updateCurrent(dt); - mIdleAnimation.setPosition(getPosition()); + mIdleAnimation.move(Vector2f.mul(getVelocity(), dt.asSeconds())); mIdleAnimation.update(dt); - System.out.println(getBoundingRect()); } - -// protected void checkCollision(){ -// Properties propsLeftTop = TmxMapLoader.getTileInstancePropertiesAt((int) (getPosition().x + get, (int) getPosition().y); -// getTransform(). -// Properties propsLeftBottom = TmxMapLoader.getTileInstancePropertiesAt((int) getPosition().x, (int) getPosition().y); -// Properties propsRightTop = TmxMapLoader.getTileInstancePropertiesAt((int) getPosition().x, (int) getPosition().y); -// Properties propsRightBottom = TmxMapLoader.getTileInstancePropertiesAt((int) getPosition().x, (int) getPosition().y); -// -// boolean isBlocking = Boolean.valueOf(props.getProperty("BlockVolume", "false")); -// if(isBlocking) -// } -// - public FloatRect getBoundingRect(){ + + public FloatRect getBoundingRect() { return getWorldTransform().transformRect(mIdleAnimation.getGlobalBounds()); } -// -// private void setCollisionRectangle(int left, int top, int width, int height){ -// mCollisionRectangle = new IntRect(left, top, width, height); -// } + + @Override + protected void onCollision(SceneNode node) { + FloatRect boundsNode = node.getBoundingRect(); + FloatRect playerRect = getBoundingRect(); + + float left, top; + left = playerRect.left; + top = playerRect.top; + + if(playerRect.left + playerRect.width > boundsNode.left){ + left = boundsNode.left - boundsNode.width; + + } else if(playerRect.left < boundsNode.left + boundsNode.width){ + left = boundsNode.left + boundsNode.width; + } + + if(playerRect.top < boundsNode.top + boundsNode.height){ + top = boundsNode.top + boundsNode.height; + } else if(playerRect.top + playerRect.height > boundsNode.top){ + top = boundsNode.top - playerRect.height; + } + mIdleAnimation.setPosition(left, top); + + //Check movement collision + + } } diff --git a/src/de/dungeonrunner/SceneNode.java b/src/de/dungeonrunner/SceneNode.java index c885c73..167bfc4 100644 --- a/src/de/dungeonrunner/SceneNode.java +++ b/src/de/dungeonrunner/SceneNode.java @@ -1,10 +1,14 @@ package de.dungeonrunner; import java.util.Properties; +import java.util.Set; import java.util.Vector; import org.jsfml.graphics.BasicTransformable; +import org.jsfml.graphics.Color; import org.jsfml.graphics.Drawable; +import org.jsfml.graphics.FloatRect; +import org.jsfml.graphics.RectangleShape; import org.jsfml.graphics.RenderStates; import org.jsfml.graphics.RenderTarget; import org.jsfml.graphics.Transform; @@ -13,9 +17,9 @@ public class SceneNode extends BasicTransformable implements Drawable { - private SceneNode mParentNode; - private Vector mChildren; - private Properties mProperties; + public SceneNode mParentNode; + public Vector mChildren; + public Properties mProperties; public SceneNode() { mChildren = new Vector<>(); @@ -24,13 +28,13 @@ public SceneNode() { @Override public void draw(RenderTarget target, RenderStates states) { - states = new RenderStates(states, Transform.combine(states.transform, getTransform())); + states = new RenderStates(states, Transform.combine(states.transform, getTransform())); drawCurrent(target, states); drawChildren(target, states); } - protected void drawCurrent(RenderTarget target, RenderStates states){ - + protected void drawCurrent(RenderTarget target, RenderStates states) { + drawBoundingRect(target, states); } private void drawChildren(RenderTarget target, RenderStates states) { @@ -44,10 +48,10 @@ public void update(Time dt) { updateChildren(dt); } - protected void updateCurrent(Time dt){ - + protected void updateCurrent(Time dt) { + } - + private void updateChildren(Time dt) { for (SceneNode node : mChildren) { node.update(dt); @@ -70,35 +74,140 @@ public SceneNode detachChild(SceneNode node) { } } + void checkNodeCollision(SceneNode node, Set collisionPairs) { + if (this != node) { + FloatRect collisionRect = collides(this, node); + if(collisionRect != null){ + collisionPairs.add(new CollisionPair(this, node)); + onCollision(node); + } + } + for (SceneNode childNode : mChildren) { + childNode.checkNodeCollision(node, collisionPairs); + } + } + + public void checkSceneCollision(SceneNode sceneGraph, Set collisionPairs) { + checkNodeCollision(sceneGraph, collisionPairs); + for (SceneNode childNode : sceneGraph.mChildren) { + if (childNode != null) { + checkSceneCollision(childNode, collisionPairs); + } + } + } + + private FloatRect collides(SceneNode node1, SceneNode node2) { + + Boolean isNode1Blocking = Boolean.valueOf(node1.getProperty("BlockVolume")); + Boolean isNode2Blocking = Boolean.valueOf(node2.getProperty("BlockVolume")); + if (isNode1Blocking && isNode2Blocking) { + return node1.getBoundingRect().intersection(node2.getBoundingRect()); + } else { + return null; + } + } + public void setParentNode(SceneNode node) { mParentNode = node; } - - public void setProperties(Properties props){ + + public void setProperties(Properties props) { mProperties = props; } - - public void addProperty(String key, String value){ + + public void addProperty(String key, String value) { mProperties.setProperty(key, value); } - - public String removeProperty(String key){ + + public String getProperty(String key) { + return mProperties.getProperty(key); + } + + public String removeProperty(String key) { return (String) mProperties.remove(key); } - + public SceneNode getParentNode() { return mParentNode; } - - public Transform getWorldTransform(){ + + public Transform getWorldTransform() { Transform transform = Transform.IDENTITY; - for(SceneNode node = this; node != null; node = node.mParentNode){ + for (SceneNode node = this; node != null; node = node.mParentNode) { transform = Transform.combine(getTransform(), transform); } return transform; } - public Vector2f getWorldPosition(){ + public Vector2f getWorldPosition() { return getWorldTransform().transformPoint(Vector2f.ZERO); } + + public Vector getChildren() { + return mChildren; + } + + public FloatRect getBoundingRect() { + return null; + } + + public static class CollisionPair { + + public SceneNode mNode1; + public SceneNode mNode2; + + public CollisionPair(SceneNode node1, SceneNode node2) { + mNode1 = node1; + mNode2 = node2; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((mNode1 == null) ? 0 : mNode1.hashCode()); + result = prime * result + ((mNode2 == null) ? 0 : mNode2.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + CollisionPair other = (CollisionPair) obj; + if (mNode1 == null) { + if (other.mNode1 != null) + return false; + } else if (!mNode1.equals(other.mNode1)) + return false; + if (mNode2 == null) { + if (other.mNode2 != null) + return false; + } else if (!mNode2.equals(other.mNode2)) + return false; + return true; + } + } + + private void drawBoundingRect(RenderTarget target, RenderStates states) { + FloatRect rect = getBoundingRect(); + Boolean isNode1Blocking = Boolean.valueOf(getProperty("BlockVolume")); + if (isNode1Blocking) { + RectangleShape shape = new RectangleShape(); + shape.setPosition(new Vector2f(rect.left, rect.top)); + shape.setSize(new Vector2f(rect.width, rect.height)); + shape.setFillColor(Color.TRANSPARENT); + shape.setOutlineColor(Color.GREEN); + shape.setOutlineThickness(1.0f); + target.draw(shape); + } + } + + protected void onCollision(SceneNode node){ + + } } diff --git a/src/de/dungeonrunner/SpriteNode.java b/src/de/dungeonrunner/SpriteNode.java index b81b2cd..742404e 100644 --- a/src/de/dungeonrunner/SpriteNode.java +++ b/src/de/dungeonrunner/SpriteNode.java @@ -1,5 +1,6 @@ package de.dungeonrunner; +import org.jsfml.graphics.FloatRect; import org.jsfml.graphics.RenderStates; import org.jsfml.graphics.RenderTarget; import org.jsfml.graphics.Sprite; @@ -19,4 +20,8 @@ protected void drawCurrent(RenderTarget target, RenderStates states) { super.drawCurrent(target, states); target.draw(mSprite); } + + public FloatRect getBoundingRect(){ + return getWorldTransform().transformRect(mSprite.getGlobalBounds()); + } }