c# - Moving Platforms in a Tile Map -
i using tile map if moving platform hits tile should go direction. using list both tilemap , platform, helps keep things neat.
the image below shows platform, in motion , when collides 1 of black circles should change directions , head opposite way going.
unfortunately having problem need find correct platform go other direction. created list in main class , not know how call upon list inside class besides main.
question:
how call upon list holding multiple objects going in different directions, in different position, , created in main class, can know if platform colliding tile?
simply put, how make platform collide tile?
here process tile map must go through used , called:
to make tile map 2 classes used, block class , game1 class (the main class).
inside block class texture, position, , blockstate (which decides thing do)
public block(texture2d texture, vector2 position, int blockstate) { this.texture = texture; this.position = position; this.blockstate = blockstate; }
then block class use method uses player class.
public player blockcollision(player player) { rectangle top = new rectangle((int)position.x + 5, (int)position.y - 10, texture.width - 10, 10); rectangle bottom = new rectangle((int)position.x + 5, (int)position.y + texture.height, texture.width - 10, 10); rectangle left = new rectangle((int)position.x - 10, (int)position.y + 5, 10, texture.height - 10); rectangle right = new rectangle((int)position.x + texture.width, (int)position.y + 5, 10, texture.height - 10); if (blockstate == 1 || (blockstate == 2 && !player.goingup)) { if (top.intersects(new rectangle((int)player.position.x, (int)player.position.y, player.texture.width, player.texture.height))) { if (player.position.y + player.texture.height > position.y && player.position.y + player.texture.height < position.y + texture.height / 2) { player.position.y = player.ground = position.y - player.texture.height; player.velocity.y = 0; player.isjumping = false; player.time = 0; player.botcollision = true; } } } return player; }
then draw method.
public void draw(spritebatch spritebatch) { spritebatch.draw(texture, new rectangle((int)position.x, (int)position.y, texture.width, texture.height), color.white); }
we move on main class game1.
i create lists both blocks , platforms.
list<block> blocks; list<movingplatform> platforms;
using char system create map.
list<char[,]> levels = new list<char[,]>(); public int tilewidth, tileheight;
then in initialize method call on lists , create map.
protected override void initialize() { blocks = new list<block>(); platforms = new list<movingplatform>(); char[,] level1 = {{'.','.','#'}, {'.','.','#'}, {'.','.','#'}}; levels.add(level1); base.initialize(); }
then void loadlevel called on.
void loadlevel(int level) { blocks.clear(); platforms.clear(); player.position = vector2.zero; tilewidth = levels[level].getlength(1); tileheight = levels[level].getlength(0); texture2d blockspritea = content.load<texture2d>("blocka2"); (int x = 0; x < tilewidth; x++) { (int y = 0; y < tileheight; y++) { //background blocks.add(new block(background, new vector2(x * 50, y * 50), 0)); //impassable blocks if (levels[level][y, x] == '#') { blocks.add(new block(blockspritea, new vector2(x * 50, y * 50), 1)); } //vertical moving platform if (levels[level][y, x] == '=') { platforms.add(new movingplatform(platform, new vector2(x * 50, y * 50), 3.0f, true)); }
then in update call on lists.
foreach (block b in blocks) { player = b.blockcollision(player); } foreach (movingplatform m in platforms) { player = m.blockcollision(player); m.update(gametime); }
finally draw method calls on them.
foreach (block b in blocks) { b.draw(spritebatch); } foreach (movingplatform m in platforms) { m.draw(spritebatch); }
i think understand question, not sure, going hazard answer anyway.
i think need move stuff out of main game class. have concept of map , bunch of stuff belongs map (platforms, blocks) it's idea encapsulate in own class, eg:
class map { public list<block> blocks; public list<movingplatform> platforms; void loadlevel(int level) { /// } }
now makes code cleaner, have map object can pass around.
so example enable movingplatform have access on map, need pass reference map parameter movingplatform constructor saves away private field. eg:
class movingplatform { map _map; public movingplatform(map map, vector2 position, ...) { _map = map; } public void update(gametime gametime) { //move platform //detect collision //have access blocks , other platforms on map //_map.blocks; //_map.platforms; } }
so in map class loadlevel() method you'd pass in 'this' first parameter of movingplatform constructor:
class map { void loadlevel(int level) { //vertical moving platform if (levels[level][y, x] == '=') { platforms.add(new movingplatform(this, ...)); } } }
you can add other map specific things (even reference player?) map class , movingplatforms automatically have access them.
this called dependency injection. movingplatform class has dependency on map , injecting dependency in through constructor.
edit:
for collision add bounds property tile , movingplatform class. makes easier current rectangle bounds of them. intersectstile method in movingplatform return true if platform intersects specified tile.
class tile { rectangle bounds { { return new rectangle((int)position.x, (int)position.y, tilewidth, tileheight); } } } class movingplatform { rectangle bounds { { return new rectangle((int)position.x, (int)position.y, platformwidth, platformheight); } } //returns true if platform intersects specified tile bool intersectstile(tile tile) { return bounds.intersects(tile.bounds); } }
then in movingplatfom class in update method platform moved each frame, check if there collision after movement. if there collision out movement , reverse platform direction, next frame move opposite way.
class movingplatform { void update(tile[] collidabletiles) { position += direction; //test collision bool iscollision = collisiontest(collidabletiles); if (iscollision) { //undo movement , change direction position -= direction; direction = newdirection; } } //returns true if platform intersects of specified tiles bool collisiontest(tile[] tiles) { foreach (tile tile in tiles) if (intersectstile(tile)) return true; return false; } }
for above work need pass in list of collidable tiles on map movingplatform update. call each movingplatform in map class, passing list of collidable tiles.
class map { list<tile> _collidabletiles; void update(gametime gametime) { foreach (movingplatform platform in movingplatforms) { platform.update(_collidabletiles); } } }
that's 1 way of doing it. better way though instead of passing in collidable tiles, movingplatform grab tiles around , test those.
class movingplatform { void update() { position += direction; //test collision tile[] tiles = _map.getnearbytiles(position); foreach (tile tile in tiles) if (tile.issolid) if (intersectstile(tile)) { //undo movement , change direction position -= direction; direction = newdirection; break; } } }
so way tiles have issolid property , set true cause moving platforms collide them.
class tile { bool issolid; }
Comments
Post a Comment