Pixel perfect collision systems implemented

Co-authored-by: r3cp3ct <45179536+r3cp3ct@users.noreply.github.com>
Co-authored-by: sigonasr2 <sigonasr2@gmail.com>
main
sigonasr2 3 years ago
parent 3fb1308222
commit 5e71aee562
  1. BIN
      sprites/knife-swing.gif
  2. 79
      src/sig/RabiClone.java
  3. 7
      src/sig/engine/objects/AnimatedObject.java
  4. 8
      src/sig/objects/Erinoah.java
  5. 5
      src/sig/objects/Player.java
  6. 9
      src/sig/objects/weapons/KnifeSwing.java

Binary file not shown.

Before

Width:  |  Height:  |  Size: 434 B

After

Width:  |  Height:  |  Size: 435 B

@ -41,6 +41,8 @@ public class RabiClone {
public static JFrame f; public static JFrame f;
public static List<Object> OBJ = new ArrayList<Object>(); public static List<Object> OBJ = new ArrayList<Object>();
public static List<AnimatedObject> FRIENDLY_OBJ = new ArrayList<AnimatedObject>();
public static List<AnimatedObject> ENEMY_OBJ = new ArrayList<AnimatedObject>();
public static boolean COLLISION[] = new boolean[(Tile.TILE_WIDTH*Map.MAP_WIDTH)*(Tile.TILE_HEIGHT*Map.MAP_HEIGHT)]; public static boolean COLLISION[] = new boolean[(Tile.TILE_WIDTH*Map.MAP_WIDTH)*(Tile.TILE_HEIGHT*Map.MAP_HEIGHT)];
public static int BASE_WIDTH = 512; public static int BASE_WIDTH = 512;
@ -133,27 +135,15 @@ public class RabiClone {
lastControllerScan = System.currentTimeMillis(); lastControllerScan = System.currentTimeMillis();
} }
Arrays.fill(PLAYER_COLLISION,false); FRIENDLY_OBJ.clear();
Arrays.fill(ENEMY_COLLISION,false); ENEMY_OBJ.clear();
for (int i = 0; i < OBJ.size(); i++) { for (int i = 0; i < OBJ.size(); i++) {
if (OBJ.get(i) instanceof RenderedObject) { if (OBJ.get(i) instanceof RenderedObject) {
RenderedObject r = (RenderedObject)OBJ.get(i); RenderedObject r = (RenderedObject)OBJ.get(i);
if (r.isFriendlyObject()) { if (r.isFriendlyObject()) {
if (OBJ.get(i) instanceof AnimatedObject) { FRIENDLY_OBJ.add((AnimatedObject)r);
AnimatedObject a = ((AnimatedObject)OBJ.get(i)); } else {
double xpos = a.getX()-level_renderer.getX()-a.getAnimatedSpr().getWidth()/2; ENEMY_OBJ.add((AnimatedObject)r);
double ypos = a.getY()-level_renderer.getY()-a.getAnimatedSpr().getHeight()/2;
int xindex = (int)a.getCurrentFrame()%a.getAnimatedSpr().getFrame_count();
int yindex = ((int)a.getCurrentFrame()%a.getAnimatedSpr().getFrame_count())/a.getAnimatedSpr().getFrame_count();
for (int y=0;y<a.getAnimatedSpr().getHeight();y++) {
for (int x=0;x<a.getAnimatedSpr().getWidth();x++) {
int index=((a.getSpriteTransform()==Transform.VERTICAL||a.getSpriteTransform()==Transform.HORIZ_VERTIC?a.getAnimatedSpr().getHeight()-y:y)+(int)ypos)*BASE_WIDTH+(a.getSpriteTransform()==Transform.HORIZONTAL||a.getSpriteTransform()==Transform.HORIZ_VERTIC?a.getAnimatedSpr().getWidth()-x:x)+(int)xpos;
if (index>=0&&index<PLAYER_COLLISION.length&&a.getAnimatedSpr().getBi_array()[(yindex*a.getAnimatedSpr().getHeight()+y)*a.getAnimatedSpr().getCanvasWidth()+xindex*a.getAnimatedSpr().getWidth()+x]!=(byte)32) {
PLAYER_COLLISION[index]=true;
}
}
}
}
} }
} }
OBJ.get(i).update(UPDATE_MULT); OBJ.get(i).update(UPDATE_MULT);
@ -161,6 +151,16 @@ public class RabiClone {
OBJ.remove(i--); OBJ.remove(i--);
} }
} }
for (int i = 0; i < FRIENDLY_OBJ.size(); i++) {
AnimatedObject f = FRIENDLY_OBJ.get(i);
for (int j=0;j<ENEMY_OBJ.size();j++) {
AnimatedObject e = ENEMY_OBJ.get(j);
if (detectCollision(e,f)) {
e.collisionEvent(f);
f.collisionEvent(e);
}
}
}
dt -= UPDATE_LOOP_NANOTIME; dt -= UPDATE_LOOP_NANOTIME;
TIME += UPDATE_LOOP_NANOTIME; TIME += UPDATE_LOOP_NANOTIME;
// System.out.println(TIME); // System.out.println(TIME);
@ -169,6 +169,49 @@ public class RabiClone {
} }
} }
private static boolean detectCollision(AnimatedObject e, AnimatedObject f) {
double x1=e.getX()-e.getAnimatedSpr().getWidth()/2,y1=e.getY()-e.getAnimatedSpr().getHeight()/2,x2=e.getX()+e.getAnimatedSpr().getWidth()/2,y2=e.getY()+e.getAnimatedSpr().getHeight()/2;
double x3=f.getX()-f.getAnimatedSpr().getWidth()/2,y3=f.getY()-f.getAnimatedSpr().getHeight()/2,x4=f.getX()+f.getAnimatedSpr().getWidth()/2,y4=f.getY()+f.getAnimatedSpr().getHeight()/2;
if (x3<x2&&y3<y2&&x4>x1&&y4>y1) //Rectangular collision detected, now check on a pixel level.
{
int sx1,sy1,w,h;
sx1 = (int)Math.max(x1,x3);
sy1 = (int)Math.max(y1,y3);
w = (int)Math.min(x2,x4)-sx1-1;
h = (int)Math.min(y2,y4)-sy1-1;
int offsetX_r1=(int)(x1>x3?0:x3-x1);
int offsetY_r1=(int)(y1>y3?0:y3-y1);
int offsetX_r2=(int)(x3>x1?0:x1-x3);
int offsetY_r2=(int)(y3>y1?0:y1-y3);
byte[] arr1=e.getAnimatedSpr().getBi_array();
int xFrame1 = (int)e.getCurrentFrame()%(e.getAnimatedSpr().getCanvasWidth()/e.getAnimatedSpr().getWidth());
int yFrame1 = ((int)e.getCurrentFrame()/(e.getAnimatedSpr().getCanvasWidth()/e.getAnimatedSpr().getWidth()))%(e.getAnimatedSpr().getCanvasHeight()/e.getAnimatedSpr().getHeight());
byte[] arr2=f.getAnimatedSpr().getBi_array();
int xFrame2 = (int)f.getCurrentFrame()%(f.getAnimatedSpr().getCanvasWidth()/f.getAnimatedSpr().getWidth());
int yFrame2 = ((int)f.getCurrentFrame()/(f.getAnimatedSpr().getCanvasWidth()/f.getAnimatedSpr().getWidth()))%(f.getAnimatedSpr().getCanvasHeight()/f.getAnimatedSpr().getHeight());
if (w>0&&h>0) {
for (int yy1=offsetY_r1;yy1<offsetY_r1+h;yy1++) {
for (int xx1=offsetX_r1;xx1<offsetX_r1+w;xx1++) {
if (arr1[((e.getSpriteTransform()==Transform.VERTICAL||e.getSpriteTransform()==Transform.HORIZ_VERTIC?e.getAnimatedSpr().getHeight()-yy1:yy1)+yFrame1*e.getAnimatedSpr().getHeight())*e.getAnimatedSpr().getCanvasWidth()+(e.getSpriteTransform()==Transform.HORIZONTAL||e.getSpriteTransform()==Transform.HORIZ_VERTIC?e.getAnimatedSpr().getWidth()-xx1:xx1)+xFrame1*e.getAnimatedSpr().getWidth()]!=(byte)32) {
for (int yy2=offsetY_r2;yy2<offsetY_r2+h;yy2++) {
for (int xx2=offsetX_r2;xx2<offsetX_r2+w;xx2++) {
if (arr2[((f.getSpriteTransform()==Transform.VERTICAL||f.getSpriteTransform()==Transform.HORIZ_VERTIC?f.getAnimatedSpr().getHeight()-yy2:yy2)+yFrame2*f.getAnimatedSpr().getHeight())*f.getAnimatedSpr().getCanvasWidth()+((f.getSpriteTransform()==Transform.HORIZONTAL||f.getSpriteTransform()==Transform.HORIZ_VERTIC?f.getAnimatedSpr().getWidth()-xx2:xx2)+xFrame2*f.getAnimatedSpr().getWidth())]!=(byte)32) {
return true;
}
}
}
}
}
}
}
}
return false;
}
private static void gameUpdateLoopStabilizer(long dt) { private static void gameUpdateLoopStabilizer(long dt) {
if (dt < UPDATE_LOOP_NANOTIME) { if (dt < UPDATE_LOOP_NANOTIME) {
lastReportedTime = System.currentTimeMillis(); lastReportedTime = System.currentTimeMillis();
@ -192,7 +235,7 @@ public class RabiClone {
continue; continue;
} }
if (!CONTROLLERS[i].poll()) { if (!CONTROLLERS[i].poll()) {
Controller[] newArr = new Controller[CONTROLLERS.length - 1]; Controller[] newArr = new Controller[CONTROLLERS.length - 2];
for (int j = 0; j < CONTROLLERS.length; j++) { for (int j = 0; j < CONTROLLERS.length; j++) {
if (j != i) { if (j != i) {
newArr[(j > i ? j - 1 : j)] = CONTROLLERS[i]; newArr[(j > i ? j - 1 : j)] = CONTROLLERS[i];

@ -2,8 +2,9 @@ package sig.engine.objects;
import sig.engine.AnimatedSprite; import sig.engine.AnimatedSprite;
import sig.engine.Panel; import sig.engine.Panel;
import sig.objects.actor.RenderedObject;
public abstract class AnimatedObject extends Object{ public abstract class AnimatedObject extends Object implements RenderedObject{
double currentFrame; double currentFrame;
double animationSpd; double animationSpd;
@ -43,5 +44,9 @@ public abstract class AnimatedObject extends Object{
public void setAnimatedSpr(AnimatedSprite animatedSpr) { public void setAnimatedSpr(AnimatedSprite animatedSpr) {
this.animatedSpr = animatedSpr; this.animatedSpr = animatedSpr;
} }
public void collisionEvent(AnimatedObject obj) {
}
} }

@ -4,8 +4,10 @@ import sig.RabiClone;
import sig.engine.Rectangle; import sig.engine.Rectangle;
import sig.engine.Sprite; import sig.engine.Sprite;
import sig.engine.Transform; import sig.engine.Transform;
import sig.engine.objects.AnimatedObject;
import sig.objects.actor.PhysicsObject; import sig.objects.actor.PhysicsObject;
import sig.objects.actor.RenderedObject; import sig.objects.actor.RenderedObject;
import sig.objects.weapons.KnifeSwing;
public class Erinoah extends PhysicsObject implements RenderedObject{ public class Erinoah extends PhysicsObject implements RenderedObject{
@ -37,7 +39,7 @@ public class Erinoah extends PhysicsObject implements RenderedObject{
@Override @Override
public void update(double updateMult) { public void update(double updateMult) {
super.update(updateMult); super.update(updateMult);
lastMoved+=updateMult; /*lastMoved+=updateMult;
lastJumped+=updateMult; lastJumped+=updateMult;
if (lastMoved>5) { if (lastMoved>5) {
switch ((int)(Math.random()*3)) { switch ((int)(Math.random()*3)) {
@ -62,7 +64,7 @@ public class Erinoah extends PhysicsObject implements RenderedObject{
lastJumped=0; lastJumped=0;
} }
} }
moveTimer-=updateMult; moveTimer-=updateMult;*/
} }
@Override @Override
@ -87,5 +89,5 @@ public class Erinoah extends PhysicsObject implements RenderedObject{
@Override @Override
public boolean isFriendlyObject() { public boolean isFriendlyObject() {
return false; return false;
} }
} }

@ -6,16 +6,16 @@ import sig.engine.Panel;
import sig.engine.Rectangle; import sig.engine.Rectangle;
import sig.engine.Sprite; import sig.engine.Sprite;
import sig.engine.Transform; import sig.engine.Transform;
import sig.engine.objects.AnimatedObject;
import sig.map.Map; import sig.map.Map;
import sig.map.Tile; import sig.map.Tile;
import sig.map.View; import sig.map.View;
import sig.objects.actor.PhysicsObject; import sig.objects.actor.PhysicsObject;
import sig.objects.actor.RenderedObject;
import sig.objects.actor.State; import sig.objects.actor.State;
import sig.objects.weapons.KnifeSwing; import sig.objects.weapons.KnifeSwing;
import sig.utils.TimeUtils; import sig.utils.TimeUtils;
public class Player extends PhysicsObject implements RenderedObject{ public class Player extends PhysicsObject{
final static boolean LEFT = false; final static boolean LEFT = false;
final static boolean RIGHT = true; final static boolean RIGHT = true;
final static long jump_fall_AnimationWaitTime = TimeUtils.millisToNanos(200); final static long jump_fall_AnimationWaitTime = TimeUtils.millisToNanos(200);
@ -372,4 +372,5 @@ public class Player extends PhysicsObject implements RenderedObject{
public boolean isFriendlyObject() { public boolean isFriendlyObject() {
return true; return true;
} }
} }

@ -4,10 +4,9 @@ import sig.engine.AnimatedSprite;
import sig.engine.Panel; import sig.engine.Panel;
import sig.engine.Transform; import sig.engine.Transform;
import sig.objects.actor.AttachableObject; import sig.objects.actor.AttachableObject;
import sig.objects.actor.RenderedObject;
import sig.engine.objects.Object; import sig.engine.objects.Object;
public class KnifeSwing extends AttachableObject implements RenderedObject{ public class KnifeSwing extends AttachableObject{
final byte frameCount = 5; //Number of frames before animation ends. final byte frameCount = 5; //Number of frames before animation ends.
@ -23,9 +22,9 @@ public class KnifeSwing extends AttachableObject implements RenderedObject{
return; return;
} }
if (getSpriteTransform()==Transform.HORIZONTAL) { if (getSpriteTransform()==Transform.HORIZONTAL) {
setX(getAttachedObject().getX()-getAnimatedSpr().getWidth()/2);
} else {
setX(getAttachedObject().getX()+getAnimatedSpr().getWidth()/2); setX(getAttachedObject().getX()+getAnimatedSpr().getWidth()/2);
} else {
setX(getAttachedObject().getX()-getAnimatedSpr().getWidth()/2);
} }
setY(getAttachedObject().getY()); setY(getAttachedObject().getY());
} }
@ -36,7 +35,7 @@ public class KnifeSwing extends AttachableObject implements RenderedObject{
@Override @Override
public Transform getSpriteTransform() { public Transform getSpriteTransform() {
return getAttached().getSpriteTransform()==Transform.HORIZONTAL||getAttached().getSpriteTransform()==Transform.HORIZ_VERTIC?Transform.NONE:Transform.HORIZONTAL; return getAttached().getSpriteTransform();
} }
@Override @Override

Loading…
Cancel
Save