From 761cfba0cfc17130bf88fa25fe839a870ee8dd0a Mon Sep 17 00:00:00 2001 From: Danny Hendrix Date: Wed, 16 Sep 2015 22:36:20 +0200 Subject: [PATCH] Refactored collision logic. --- lib/game/level.dart | 6 +- lib/game/leveltile.dart | 46 ++++------ lib/game/render.dart | 2 +- lib/game/renderobject.dart | 25 ++++-- lib/game/renderobject/door.dart | 4 +- lib/game/renderobject/gameobject.dart | 76 ++++++++-------- lib/game/renderobject/player.dart | 124 ++++++++++---------------- 7 files changed, 127 insertions(+), 156 deletions(-) diff --git a/lib/game/level.dart b/lib/game/level.dart index 311c858..0898f90 100644 --- a/lib/game/level.dart +++ b/lib/game/level.dart @@ -100,9 +100,9 @@ class Level { } - void isCollision(GameObject object) + void repairCollision(GameObject object) { - object.checkLevelBorderCollision(); + object.repairLevelBorderCollision(); int tileCollStartX = (object.collisionx/32).floor().toInt(); int tileCollEndX = (object.collisionx2/32).ceil().toInt(); @@ -121,7 +121,7 @@ class Level intkey = iy * tilesx + ix; if(leveltiles.length <= intkey || intkey < 0) continue; - leveltiles[intkey].isCollision(object); + leveltiles[intkey].repairCollision(object); } } diff --git a/lib/game/leveltile.dart b/lib/game/leveltile.dart index 45c1558..f10eef9 100644 --- a/lib/game/leveltile.dart +++ b/lib/game/leveltile.dart @@ -16,21 +16,23 @@ class LevelTile int _tileid = 0; List objects; bool changed = true; - CollisionField collision; + bool hascollision = false; Sprite sprite; RenderLayer layer; Level level; + static CollisionField TILE_COLLISIONFIELD = new CollisionField(0,0,32,32); + void set tileid(int value) { _tileid = value; sprite.spritex = (_tileid - 1) * 32; if(_tileid != 0) - setCollision(true); + hascollision = true; else - setCollision(false); + hascollision = false; } int get tileid => _tileid; @@ -41,7 +43,7 @@ class LevelTile layer.height = h; if(_tileid != 0) - setCollision(true); + hascollision = true; sprite = new Sprite("resources/images/images.png",(_tileid - 1) * 32,0,32,32); } @@ -51,7 +53,6 @@ class LevelTile if(objects == null) objects = new List(); objects.add(obj); - changed = true; repaint(); } @@ -64,47 +65,36 @@ class LevelTile return remove(obj); if(index == -1) return insert(obj); - changed = true; repaint(); } - - void setCollision(bool value) - { - if(value == false) - collision = null; - else - collision = new CollisionField(0,0,w,h); - } - void isCollision(RenderObject obj) + void repairCollision(RenderObject obj) { - - if(collision != null) + if(hascollision) { - obj.checkTileCollision(this); - return; + obj.repairCollisionTile(this); + return; } if(objects == null) return; - - if( ( + //check if the collisionfield of the object within the bounderies of this tile + if( !( obj.collisionx2 > x && obj.collisionx < x+w && obj.collisiony2+1 > y && obj.collisiony < y+h - ) == false + ) ) { return; } - RenderObject levelobject; + //loop through objects currently on this tile and check for collisions for(int i = 0; i < objects.length; i++) { if(objects[i] == obj) continue; - levelobject = objects[i]; - obj.checkObjectCollision(levelobject); + obj.repairCollisionObject(objects[i]); } } @@ -115,10 +105,9 @@ class LevelTile if(index == -1) return; objects.removeAt(index); - //objects.removeRange(index, 1); if(objects.length == 0) objects = null; - changed = true; + repaint(); } @@ -164,6 +153,9 @@ class LevelTile void repaint() { + if(changed) + return; + changed = true; level.updatetiles.add(this); } } diff --git a/lib/game/render.dart b/lib/game/render.dart index 397e378..8f482e3 100644 --- a/lib/game/render.dart +++ b/lib/game/render.dart @@ -40,6 +40,6 @@ class Render game.level.draw(layer, game.camera.x, game.camera.y); - layer.ctx.fillText("FPS: ${game..gameloop.fps}", 10, 20); + layer.ctx.fillText("FPS: ${game.gameloop.fps}", 10, 20); } } diff --git a/lib/game/renderobject.dart b/lib/game/renderobject.dart index c26d7d2..c7f1202 100644 --- a/lib/game/renderobject.dart +++ b/lib/game/renderobject.dart @@ -50,7 +50,6 @@ class RenderObject void paint() { - } void drawCollision(RenderLayer targetlayer, int offsetx, int offsety) @@ -78,19 +77,27 @@ class RenderObject targetlayer.ctx.drawImage(layer.canvas, (x-offsetx).round().toInt(), (y-offsety).round().toInt()); } - bool checkCollisionField(double relativex, double relativey, CollisionField collisionfield) + bool isCollisionField(double relativex, double relativey, CollisionField collisionfield) { - return false; + if(collision == null) + return false; + return + collisionx2 > relativex + && collisionx < relativex+collisionfield.x2 + && collisiony2 > relativey + && collisiony < relativey+collisionfield.y2; } - - bool checkTileCollision(LevelTile tile) + void repairCollisionTile(LevelTile tile) { - return checkCollisionField(tile.x.toDouble(), tile.y.toDouble(),tile.collision); } - - bool checkObjectCollision(RenderObject o) + void repairCollisionObject(RenderObject obj) + { + } + void onTileCollision(LevelTile tile) + { + } + void onObjectCollision(RenderObject o) { - return checkCollisionField(o.x, o.y, o.collision); } void updateDrawLocation([bool remove = false]) diff --git a/lib/game/renderobject/door.dart b/lib/game/renderobject/door.dart index 4d0b634..10a1420 100644 --- a/lib/game/renderobject/door.dart +++ b/lib/game/renderobject/door.dart @@ -32,7 +32,7 @@ class Door extends InteractiveObject if(layerwidth > w) { w = layerwidth; - collision.x += ((w-25)/2).toInt(); + collision.x += (w-25)~/2; } collision.y += layerheight; h += layerheight; @@ -49,7 +49,7 @@ class Door extends InteractiveObject { int drawx = 0; if(w > 25) - drawx = ((w-25)/2).toInt(); + drawx = (w-25)~/2; sprite.drawOnPosition(drawx,layerheight,(over == true)?1:0,0,layer); } diff --git a/lib/game/renderobject/gameobject.dart b/lib/game/renderobject/gameobject.dart index a3a6bc5..e31175c 100644 --- a/lib/game/renderobject/gameobject.dart +++ b/lib/game/renderobject/gameobject.dart @@ -26,102 +26,100 @@ class GameObject extends RenderObject { } - bool checkLevelBorderCollision() + void repairLevelBorderCollision() { - bool ret = false; if(collisionx2 > game.level.x+game.level.w) - { x = game.level.x+game.level.w-collision.x2; - ret = true; - } if(collisionx < game.level.x) - { x = game.level.x-collision.x; - ret = true; - } if(collisiony2 > game.level.y+game.level.h) { y = game.level.y+game.level.h-collision.y2; onPlatform = true; - ret = true; } if(collisiony < game.level.y) - { y = game.level.y-collision.y; - ret = true; - } if(collisiony2+1 > game.level.y+game.level.h) onPlatform = true; - return ret; } - - bool checkCollisionField(double relativex, double relativey, CollisionField collisionfield) + void repairCollisionTile(LevelTile tile) + { + if(isCollisionField(tile.x.toDouble(),tile.y.toDouble(),LevelTile.TILE_COLLISIONFIELD)) + onTileCollision(tile); + } + void repairCollisionObject(RenderObject obj) + { + if(isCollisionField(obj.x,obj.y,obj.collision)) + onObjectCollision(obj); + } + + void onTileCollision(LevelTile tile) { //collision double dif_x = prev_x - x; double dif_y = prev_y - y; - + /* //if no collision, only check for platform if( ( - collisionx2 > relativex - && collisionx < relativex+collisionfield.x2 - && collisiony2 > relativey - && collisiony < relativey+collisionfield.y2 + collisionx2 > tile.x + && collisionx < tile.x+tile.collision.x2 + && collisiony2 > tile.y + && collisiony < tile.y+tile.collision.y2 ) == false) { //no collision but it might be on top of the object if( ( - collisionx2 > relativex - && collisionx < relativex+collisionfield.x2 - && collisiony2+1 > relativey - && collisiony < relativey+collisionfield.y2 + collisionx2 > tile.x + && collisionx < tile.x+tile.collision.x2 + && collisiony2+1 > tile.y + && collisiony < tile.y+tile.collision.y2 ) == true) { onPlatform = true; } - return false; + return; } //not moved: if(dif_x == 0 && dif_y == 0) - return false; - + return; + */ double overlap_x = 0.0; double overlap_y = 0.0; if(dif_x > 0)//left - overlap_x = relativex + collisionfield.x2 - collisionx; + overlap_x = tile.x + LevelTile.TILE_COLLISIONFIELD.x2 - collisionx; if(dif_x < 0)//right - overlap_x = relativex + collisionfield.x - collisionx2; + overlap_x = tile.x + LevelTile.TILE_COLLISIONFIELD.x - collisionx2; if(dif_y > 0)//top - overlap_y = relativey + collisionfield.y2 - collisiony; + overlap_y = tile.y + LevelTile.TILE_COLLISIONFIELD.y2 - collisiony; if(dif_y < 0)//bottom - overlap_y = relativey + collisionfield.y - collisiony2; + overlap_y = tile.y + LevelTile.TILE_COLLISIONFIELD.y - collisiony2; double percentage = 0.0; double percentage_y = 0.0; - + if(dif_x != 0) percentage = (dif_x - overlap_x) / dif_x; if(dif_y != 0) percentage_y = (dif_y - overlap_y) / dif_y; percentage = Math.max(percentage, percentage_y); - + x = prev_x - (dif_x * percentage); y = prev_y - (dif_y * percentage); - + //check if on platform after the obj moved if( ( - collisionx2 > relativex - && collisionx < relativex+collisionfield.x2 - && collisiony2+1 > relativey - && collisiony < relativey+collisionfield.y2 + collisionx2 > tile.x + && collisionx < tile.x+LevelTile.TILE_COLLISIONFIELD.x2 + && collisiony2+1 > tile.y + && collisiony < tile.y+LevelTile.TILE_COLLISIONFIELD.y2 ) == true) { onPlatform = true; } - return true; + return; } diff --git a/lib/game/renderobject/player.dart b/lib/game/renderobject/player.dart index 2b89427..10d6d16 100644 --- a/lib/game/renderobject/player.dart +++ b/lib/game/renderobject/player.dart @@ -108,15 +108,6 @@ class Player extends GameObject the key that is pressed first is first in the array. The key that is last in the array is handled. */ - - /* - int index = movepriority.indexOf(move); - if(index > -1) - movepriority.removeRange(index, 1); - if(activate == true) - movepriority.add(move); - */ - movepriority.remove(move); if(activate == true) movepriority.add(move); @@ -156,40 +147,41 @@ class Player extends GameObject move = movepriority.last; setState(move); - prev_x = x; - prev_y = y; - handleState(); - + + //apply vector + x += vector.xspeed; + y += vector.yspeed; + bool moved = (x != prev_x || y != prev_y); - + if(moved) { + //check for collisions + onPlatform = false; + game.level.repairCollision(this); + if(onPlatform == false) + changeState(STATE_INAIR); + //clear hoverobject? if(hoverobject != null) { if( ( - collisionx2 > hoverobject.collisionx - && collisionx < hoverobject.collisionx2 - && collisiony2 > hoverobject.collisiony - && collisiony < hoverobject.collisiony2 - ) == false + collisionx2 > hoverobject.collisionx + && collisionx < hoverobject.collisionx2 + && collisiony2 > hoverobject.collisiony + && collisiony < hoverobject.collisiony2 + ) == false ) { hoverobject.onOut(this); hoverobject = null; } } - - onPlatform = false; - game.level.isCollision(this); - if(onPlatform == false) - changeState(STATE_INAIR); - - framechanged = true; - //set the camera position relative to the player - game.camera.centerObject(this); - } + framechanged = true; + //set the camera position relative to the player + game.camera.centerObject(this); + } //redraw item if(framechanged == true) @@ -202,11 +194,15 @@ class Player extends GameObject //when the state is inAir, changing state is not possible if(state == STATE_INAIR && newState != STATE_DEF) return; + if(newState == STATE_INAIR) + onPlatform = false; state = newState; } void setState(int move) { + prev_x = x; + prev_y = y; switch(move) { case MOVE_RIGHT: @@ -266,9 +262,6 @@ class Player extends GameObject framechanged = changeImage(_INAIR); break; } - //apply vector - x += vector.xspeed; - y += vector.yspeed; } void paint() @@ -292,26 +285,32 @@ class Player extends GameObject layer.ctx.setFillColorRgb(0,255,0); layer.ctx.fillRect(labeloffset+1, 1+labelheight, healthw, 4); } - - bool checkCollisionField(double relativex, double relativey, CollisionField collisionfield) + + bool repairLevelBorderCollision() { - bool res = super.checkCollisionField(relativex, relativey, collisionfield); - if(res == false) - return false; - - if(onPlatform == true) - changeState(STATE_DEF); + if(y > game.level.y+game.level.h) + die(); - vector.clear(); - return true; + return false; } - - bool checkTileCollision(LevelTile tile) + void repairCollisionTile(LevelTile tile) { - bool res = super.checkTileCollision(tile); - if(res == false) - return false; - + super.repairCollisionTile(tile); + if(isCollisionField(tile.x.toDouble(),tile.y.toDouble()-1,LevelTile.TILE_COLLISIONFIELD)) + onPlatform = true; + } + void repairCollisionObject(RenderObject obj) + { + super.repairCollisionObject(obj); + if(isCollisionField(obj.x,obj.y-1,obj.collision)) + onPlatform = true; + } + void onTileCollision(LevelTile tile) + { + super.onTileCollision(tile); + if(state == STATE_INAIR && onPlatform == true) + changeState(STATE_DEF); + vector.clear(); //spikes if(tile.tileid == 4) { @@ -322,38 +321,13 @@ class Player extends GameObject this.vector.addVector(_SPIKES_RIGHT); addHealth(-0.2); } - - return true; - } - - bool checkLevelBorderCollision() - { - if(y > game.level.y+game.level.h) - die(); - - return false; } - - bool checkObjectCollision(RenderObject o) + void onObjectCollision(RenderObject o) { - if(o is InteractiveObject == false) - return checkObjectCollision(o); - - //over object? - if( ( - collisionx2 > o.collisionx - && collisionx < o.collisionx2 - && collisiony2 > o.collisiony - && collisiony < o.collisiony2 - ) == false) - return false; - if(o is InteractiveObject == false || hoverobject != null || hoverobject == o) - return false; - + return; InteractiveObject so = o; so.onOver(this); hoverobject = so; - return true; } }