Cool! Glad it could be worked out :)

Posts made by nospoone
-
RE: HaxeFlixel forum: Edit Profile broken..?
-
RE: HaxeFlixel forum: Edit Profile broken..?
Not sure what happened, but upgrading the forum version (which it was due for anyways) seems to have fixed the issue! Can you verify that you can edit your profile and let me know?
:D
-
RE: HaxeFlixel forum: Edit Profile broken..?
Hi!
How did you register? Via one of the SSO options (Facebook, Twitter, etc), or regularly?
-
RE: simple raycast?
Hey! Sorry 'bout that. We've had a couple reports of this and disabled Akismet for the time being. Can you see if it works now?
-
RE: [SOLVED] 2D Array swapping dimensions / PCG tilemap issues
Alright, @sasik on the HaxeFlixel Discord resolved this. I was storing my tiles in
MapData[x][y]
, whereasFlxTilemap.loadFrom2dArray()
expectsMapData[y][x]
. Had I used non-square maps I would've probably caught that earlier! He also gave me great tips on using 1D vectors instead to gain performance.:D
-
RE: [SOLVED] 2D Array swapping dimensions / PCG tilemap issues
Good idea. However,
trace
ing out if we set the data more than once returns nothing. Which means they are indeed being processed only once. -
[SOLVED] 2D Array swapping dimensions / PCG tilemap issues
Hey there!
I'm having problems which make me question my sanity. They aren't directly related to HaxeFlixel, but I'm at a loss and I need help. Here we go...
The Problem
I use cellular automata to generate a cave shape, using
Bool
s, wheretrue
means solid andfalse
means empty. Here are the relevant parts from the class:// Generation Parameters public var Width:Int = 60; public var Height:Int = 60; public var SolidChance:Float = 0.395; private var deathLimit:Int = 3; private var birthLimit:Int = 4; // Data public var MapData:Array<Array<Bool>> = new Array<Array<Bool>>(); public var TilemapData:Array<Array<Int>> = new Array<Array<Int>>(); public function new() { // This fills the array with random data seedMap(); // This smooths out the generated caves for (i in 0...4) { MapData = simulate(); } // Finds rooms, connects them and removes unused chunks processMap(); // Generates the data for use with FlxTilemap generateTilemap(); } private function seedMap() { for (x in 0...Width) { if (MapData[x] == null) { MapData[x] = new Array<Bool>(); } for (y in 0...Height) { if (y == 0 || y == Height - 1 || x == 0 || x == Width - 1) { MapData[x][y] = true; } else { MapData[x][y] = FlxG.random.bool(SolidChance * 100); } } } private function simulate():Array<Array<Bool>> { var simulatedMap:Array<Array<Bool>> = MapData.copy(); for (x in 0...Width) { for (y in 0...Height) { var neighbours:Int = countAliveNeighbours(x, y); if (MapData[x][y]) { if (neighbours < deathLimit) { simulatedMap[x][y] = false; } else { simulatedMap[x][y] = true; } } else { if (neighbours > birthLimit) { simulatedMap[x][y] = true; } else { simulatedMap[x][y] = false; } } } } return simulatedMap; } private function processMap():Void { var wallRegions:Array<Array<Tile>> = getRegion(true); var wallTresholdSize:Int = 50; for (wallRegion in wallRegions) { if (wallRegion.length < wallTresholdSize) { for (tile in wallRegion) { MapData[tile.X][tile.Y] = false; } } } var roomRegions:Array<Array<Tile>> = getRegion(false); var roomTresholdSize:Int = 50; var survingRooms:Array<Room> = new Array<Room>(); for (roomRegion in roomRegions) { if (roomRegion.length < roomTresholdSize) { for (tile in roomRegion) { MapData[tile.X][tile.Y] = true; } } else { survingRooms.push(new Room(roomRegion, MapData)); } } survingRooms.sort(function (roomA:Room, roomB:Room):Int { if (roomA.RoomSize > roomB.RoomSize) { return -1; } else if (roomA.RoomSize < roomB.RoomSize) { return 1; } return 0; }); survingRooms[0].IsMainRoom = true; survingRooms[0].IsAccessibleFromMainRoom = true; ConnectClosestRooms(survingRooms); } private function generateTilemap():Void { for (x in 0...Width) { if (TilemapData[x] == null) { TilemapData[x] = new Array<Int>(); } for (y in 0...Height) { if (MapData[x][y]) { TilemapData[x][y] = 15; if (HasWallAt(x - 1, y) && HasWallAt(x + 1, y) && HasWallAt(x, y - 1) && HasWallAt(x, y + 1)) { // we're walled off TilemapData[x][y] = 6; } if (!HasWallAt(x - 1, y) && HasWallAt(x + 1, y) && HasWallAt(x, y - 1) && HasWallAt(x, y + 1)) { // Left to us is empty, rest is filled TilemapData[x][y] = 5; } if (!HasWallAt(x + 1, y) && HasWallAt(x - 1, y) && HasWallAt(x, y - 1) && HasWallAt(x, y + 1)) { // Right to us is empty, rest is filled TilemapData[x][y] = 7; } if (!HasWallAt(x, y - 1) && HasWallAt(x, y + 1) && HasWallAt(x - 1, y) && HasWallAt(x + 1, y)) { // Above us is empty, is filled TilemapData[x][y] = 2; } if (!HasWallAt(x, y + 1) && HasWallAt(x, y - 1) && HasWallAt(x - 1, y) && HasWallAt(x + 1, y)) { // Below us is empty TilemapData[x][y] = 10; } } else { TilemapData[x][y] = (FlxG.random.bool(5) ? 4 : 8); } } } } // Utility functions private function countAliveNeighbours(x:Int, y:Int):Int { var count:Int = 0; for (i in -1...2) { for (j in -1...2) { var neighbour_x:Int = x + i; var neighbour_y:Int = y + j; if (i == 0 && j == 0) { } else if (neighbour_x < 0 || neighbour_y < 0 || neighbour_x >= Width || neighbour_y >= Height) { count = count + 1; } else if (MapData[neighbour_x][neighbour_y]) { count = count + 1; } } } return count; } private function isInMapRange(x:Int, y:Int):Bool { return x >= 0 && x < Width && y >= 0 && y < Height; } public function HasWallAt(x:Int, y:Int):Bool { if (isInMapRange(x, y)) { return MapData[x][y]; } return true; } }
It goes through 4 steps:
- Seed the map with random values
- Simulate the cellular automata to create shapes & smooth it out
- Check for small walls or rooms and remove them, and connect the remaining rooms
- Generate the tilemap data.
This works well, until step 4. As far as I can tell, this line of code checks if the tile to the right is not a wall (
false
), and that the rest (top, left, and bottom) are walls (true
).if (!HasWallAt(x + 1, y) && HasWallAt(x - 1, y) && HasWallAt(x, y - 1) && HasWallAt(x, y + 1)) { // ... }
However, it does not. This
if
returns true only if the bottom one is not a wall (false
) and the rest are walls (true
). By going through and checking where all of them end up actually verifying where there's a wall or not, I found out that in theseHasWallAt()
calls,X
meansY
andY
meansX
:if (!HasWallAt(x - 1, y) && HasWallAt(x + 1, y) && HasWallAt(x, y - 1) && HasWallAt(x, y + 1)) { // This evaluates to true when: // The TOP tile is empty, and the rest are filled } if (!HasWallAt(x + 1, y) && HasWallAt(x - 1, y) && HasWallAt(x, y - 1) && HasWallAt(x, y + 1)) { // This evaluates to true when: // The BOTTOM tile is empty, and the rest are filled } if (!HasWallAt(x, y - 1) && HasWallAt(x, y + 1) && HasWallAt(x - 1, y) && HasWallAt(x + 1, y)) { // This evaluates to true when: // The LEFT tile is empty, and the rest are filled } if (!HasWallAt(x, y + 1) && HasWallAt(x, y - 1) && HasWallAt(x - 1, y) && HasWallAt(x + 1, y)) { // This evaluates to true when: // The RIGHT tile is empty, and the rest are filled }
You can see here how they aren't in the right place (ignore the X tiles, it's corners)
Here's my actual question: is it possible that the array dimensions get switched around?
-
Forum Stability
Hello!
Just wanted to let you all know that we've been aware of the stability issues with the forum this past week. I've upgraded the VPS and setup some other stuff to help it run smoother.
Sorry! It should be better now :D
-
RE: A Wicked Curse
I've been coming across screenshots on Twitter... Looks fun! Keep it up!