Projectiles Lagging, Not Fully Being Deleted - c#

For me this bug is game breaking, I am using four different Lists that control rockets that shoot out of many launchers. The launchers are also held in a list:
Launchers = new List<Launcher>();
RocketsUp = new List<Rectangle>();
RocketsDown = new List<Rectangle>();
RocketsLeft = new List<Rectangle>();
RocketsRight = new List<Rectangle>();
If you just want to see the full thing Here is the project. (Please Understand that it's a compleat mess, I am trying to make it work, if I had more time then 3 to 4 weeks to finish this I would try and make it more cleaned up)
Questions
The Rockets will shoot out but the right rockets are stopping at random intervals, up, down, and left are work fine, how?
If I let the game play a little it starts to slow down after a while, I had thought that I had to many rockets in game firing but they're firing and being destroyed so shouldn't the game work fine since the rockets are being cleared as fast as there being spawned?
End Questions
Note: (I have multiple levels and when I jump to the next the lag goes away since I have a clear all in a method):
Launchers.Clear();
RocketsUp.Clear();
RocketsDown.Clear();
RocketsRight.Clear();
RocketsLeft.Clear();
What these launchers will do is fire a projectile every set amount of seconds in a strait line until they make contact with a block or player.
I have a foreach loop go through each launcher position and spawn a rocket based on what direction the launcher is facing, 1 = Up, 2 = Down, 3 = Right, 4 = Left:
foreach (Launcher l in Launchers)
{
l.Updata(gameTime);
if (rocketTime > rocketMax)
{
if (l.Direction == 1)
RocketsUp.Add(new Rectangle((int)l.Position.X + 11, (int)l.Position.Y, 9, 18));
if (l.Direction == 2)
RocketsDown.Add(new Rectangle((int)l.Position.X + 11, (int)l.Position.Y, 9, 18));
if (l.Direction == 3)
RocketsRight.Add(new Rectangle((int)l.Position.X, (int)l.Position.Y + 11, 18, 9));
if (l.Direction == 4)
RocketsLeft.Add(new Rectangle((int)l.Position.X, (int)l.Position.Y + 11, 18, 9));
}
}
Then a for loop is called for each rocket list and define their size since the texture is not the correct size:
if (rocketTime > rocketMax)
rocketTime = 0;
for (int i = 0; i < RocketsUp.Count; i++)
{
RocketsUp[i] = new Rectangle(RocketsUp[i].X, RocketsUp[i].Y - 3, RocketsUp[i].Width, RocketsUp[i].Height);
}
for (int i = 0; i < RocketsDown.Count; i++)
{
RocketsDown[i] = new Rectangle(RocketsDown[i].X, RocketsDown[i].Y + 3, RocketsDown[i].Width, RocketsDown[i].Height);
}
for (int i = 0; i < RocketsLeft.Count; i++)
{
RocketsRight[i] = new Rectangle(RocketsRight[i].X + 3, RocketsRight[i].Y, RocketsRight[i].Width, RocketsRight[i].Height);
}
for (int i = 0; i < RocketsLeft.Count; i++)
{
RocketsLeft[i] = new Rectangle(RocketsLeft[i].X - 3, RocketsLeft[i].Y, RocketsLeft[i].Width, RocketsLeft[i].Height);
}
Then the rockets are drawn in the Draw method:
for (int i = 0; i < RocketsUp.Count; i++)
{
spriteBatch.Draw(rocketUp, new Rectangle(RocketsUp[i].X,
RocketsUp[i].Y,
RocketsUp[i].Width,
RocketsUp[i].Height),
Color.White);
}
for (int i = 0; i < RocketsDown.Count; i++)
{
spriteBatch.Draw(rocketDown, new Rectangle(RocketsDown[i].X,
RocketsDown[i].Y,
RocketsDown[i].Width,
RocketsDown[i].Height),
Color.White);
}
for (int i = 0; i < RocketsRight.Count; i++)
{
spriteBatch.Draw(rocketRight, new Rectangle(RocketsRight[i].X, RocketsRight[i].Y, RocketsRight[i].Width, RocketsRight[i].Height), Color.White);
}
for (int i = 0; i < RocketsLeft.Count; i++)
{
spriteBatch.Draw(rocketLeft, new Rectangle(RocketsLeft[i].X, RocketsLeft[i].Y, RocketsLeft[i].Width, RocketsLeft[i].Height), Color.White);
}
Finally the Rockets are called in another class called Block:
public Player BlockCollision(Player player, GameTime gameTime, Game1 game1)
{
this.game1 = game1;
kbState = Keyboard.GetState();
Rectangle BlockRectangle = new Rectangle((int)Position.X, (int)Position.Y, Texture.Width, Texture.Height);
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);
Rectangle personRectangle = new Rectangle((int)player.Position.X, (int)player.Position.Y, player.Texture.Width, player.Texture.Height);
for (int i = 0; i < game1.RocketsDown.Count; i++)
{
Vector2 Rocket = new Vector2(game1.RocketsDown[i].X, game1.RocketsDown[i].Y);
if (personRectangle.Intersects(new Rectangle((int)Rocket.X, (int)Rocket.Y, game1.rocketDown.Width, game1.rocketDown.Height)))
{
player.Dead = true;
}
}
for (int i = 0; i < game1.RocketsUp.Count; i++)
{
Vector2 Rocket = new Vector2(game1.RocketsUp[i].X, game1.RocketsUp[i].Y);
if (personRectangle.Intersects(new Rectangle((int)Rocket.X, (int)Rocket.Y, game1.rocketUp.Width, game1.rocketUp.Height)))
{
player.Dead = true;
}
}
for (int i = 0; i < game1.RocketsLeft.Count; i++)
{
Vector2 Rocket = new Vector2(game1.RocketsLeft[i].X, game1.RocketsLeft[i].Y);
if (personRectangle.Intersects(new Rectangle((int)Rocket.X, (int)Rocket.Y, game1.rocketLeft.Width, game1.rocketLeft.Height)))
{
player.Dead = true;
}
}
for (int i = 0; i < game1.RocketsRight.Count; i++)
{
Vector2 Rocket = new Vector2(game1.RocketsRight[i].X, game1.RocketsRight[i].Y);
if (personRectangle.Intersects(new Rectangle((int)Rocket.X, (int)Rocket.Y, game1.rocketRight.Width, game1.rocketRight.Height)))
{
player.Dead = true;
}
}
if (BlockState > 0)
{
for (int i = 0; i < game1.RocketsDown.Count; i++)
{
Vector2 Rocket = new Vector2(game1.RocketsDown[i].X, game1.RocketsDown[i].Y);
if (top.Intersects(new Rectangle((int)Rocket.X, (int)Rocket.Y, game1.rocketDown.Width, game1.rocketDown.Height)))
{
game1.RocketsDown.RemoveAt(i);
}
}
for (int i = 0; i < game1.RocketsUp.Count; i++)
{
Vector2 Rocket = new Vector2(game1.RocketsUp[i].X, game1.RocketsUp[i].Y);
if (bottom.Intersects(new Rectangle((int)Rocket.X, (int)Rocket.Y, game1.rocketUp.Width, game1.rocketUp.Height)))
{
game1.RocketsUp.RemoveAt(i);
}
}
for (int i = 0; i < game1.RocketsLeft.Count; i++)
{
Vector2 Rocket = new Vector2(game1.RocketsLeft[i].X, game1.RocketsLeft[i].Y);
if (right.Intersects(new Rectangle((int)Rocket.X, (int)Rocket.Y, game1.rocketLeft.Width, game1.rocketLeft.Height)))
{
game1.RocketsLeft.RemoveAt(i);
}
}
for (int i = 0; i < game1.RocketsRight.Count; i++)
{
Vector2 Rocket = new Vector2(game1.RocketsRight[i].X, game1.RocketsRight[i].Y);
if (left.Intersects(new Rectangle((int)Rocket.X, (int)Rocket.Y, game1.rocketRight.Width, game1.rocketRight.Height)))
{
game1.RocketsRight.RemoveAt(i);
}
}
}

Check this piece of code:
for (int i = 0; i < RocketsLeft.Count; i++)
{
RocketsRight[i] = new Rectangle(RocketsRight[i].X + 3, RocketsRight[i].Y, RocketsRight[i].Width, RocketsRight[i].Height);
}
for (int i = 0; i < RocketsLeft.Count; i++)
{
RocketsLeft[i] = new Rectangle(RocketsLeft[i].X - 3, RocketsLeft[i].Y, RocketsLeft[i].Width, RocketsLeft[i].Height);
}
You have used RocketLeft.Count where you should have used RocketRight.
Edit: Also, try disposing your 'destroyed' rockets using Rectangle.Dispose(). It may help to free up some resources.

Related

Issues with Steering Behavior Seperation

The problem
I am trying to procedurally generate dungeon rooms with random X, Y sizes inside of a radius (r). However, even after I validate that the starting grid (origin of the "room") is not in the same position as other origins after running the separation function there are rooms still building inside of each other.
Solutions I have tried
I tried using math to calculate an optimal radius that will be able to fit the average of all the room sizes * amount of rooms. However, the separation should hypothetically work with any radius (though I want to keep them relatively close in order to keep hallways short).
Code
All my code is based on one tile. This means that all calculations are using one tile, and will remain one tile until the very end, then I scale them up.
private void GenerateRooms(int amount)
{
// init sizes
Vector2[] room_sizes = new Vector2[amount];
for (int i = 0; i < amount; i++)
{
room_sizes[i] = new Vector2(Random.Range(minimum_room_height, maximum_room_height), Random.Range(minimum_room_width, maximum_room_width));
}
float biggest_room = calculations.CalculateBiggest(room_sizes);
Vector2[] room_points = new Vector2[amount];
Vector2[] used_points = new Vector2[amount];
float radius = calculations.CalculateAverage(room_sizes) * amount;
for (int i = 0; i < amount; i++)
{
do {
Vector2 test_point = new Vector2(Random.Range(-radius, radius), Random.Range(-radius, radius));
foreach (Vector2 point in used_points) {
if (test_point == point) {
continue;
} else {
room_points[i] = test_point;
used_points[i] = test_point;
break;
}
}
} while (Vector2.Distance(Vector2.zero, room_points[i]) < radius);
}
for (int i = 0; i < amount; i++)
{
//Vector2 origin = room_points[i];
Vector3 position = calculations.computeSeperate(room_points, room_points[i], biggest_room);
//position = new Vector3(position.x + origin.x, position.y + origin.y, 0);
Vector3Int location = tile_map.WorldToCell(position);
tile_map.SetTile(location, tile);
calculations.scaleUpRooms(position, room_sizes[i].x, room_sizes[i].y, tile_map, tile);
}
}
The above is code for calling all the functions and validating the points. Here are the important functions (calculation functions):
public Vector2 computeSeperate(Vector2[] point_array, Vector2 target_point, float minimum_distance)
{
int neighbor_count = 0;
for (int i = 0; i < point_array.Length; i++)
{
if (point_array[i] != target_point)
{
if (Vector2.Distance(target_point, point_array[i]) < minimum_distance * 2)
{
target_point.x += point_array[i].x - target_point.x;
target_point.y += point_array[i].y - target_point.y;
neighbor_count++;
}
}
}
if (neighbor_count == 0)
{
return target_point;
} else
{
target_point.x /= neighbor_count;
target_point.y /= neighbor_count;
target_point.x *= -1;
target_point.y *= -1;
target_point.Normalize();
return target_point;
}
}
public void scaleUpRooms(Vector2 base_point, float scale_x, float scale_y, Tilemap tile_map, Tile tile) // ex: 5x5
{
List<Vector2> Calculate(Vector2 size)
{
List<Vector2> results = new List<Vector2>();
for (int i = 0; i < size.y; i++)
for (int o = 0; o < size.x; o++)
results.Add(new Vector2(o, i) + (new Vector2(size.x % 2 != 0 ? .5f : 1, size.y % 2 != 0 ? .5f : 1) - (size / 2)));
string st = "";
for (int i = 0; i < results.Count; i++)
st += "\n" + results[i].ToString();
return results;
}
Vector2 desired_scale = new Vector2(scale_x, scale_y);
List<Vector2> Offsets = Calculate(desired_scale);
for (int i = 0; i < Offsets.Count; i++)
{
Vector3 position = base_point + Offsets[i];
Vector3Int location = tile_map.WorldToCell(position);
tile_map.SetTile(location, tile);
}
}

Procedural world generation can't handle big maps

so, I'm making a terraria-like game in unity 2019 on windws 10 using c# which has procedurally generated tilemaps and i have this script attached to a grid:
using UnityEngine;
using AccidentalNoise;
using System.Collections.Generic;
using UnityEngine.Tilemaps;
using System;
public class CompileTerrain : MonoBehaviour
{
public TileBase dirtTile;
public TileBase grassTile;
public TileBase stoneTile;
public List<GameObject> fractalLayers = new List<GameObject>();
public Tilemap grid;
public int width;
public int height;
public float seed;
public int caveSmoothness = 2;
void Start()
{
grid.ClearAllTiles();
int touchCount = 0;
Vector3Int newPos;
double nx, ny;
ModuleBase combinedTerrain = CavesAndMountains((uint)seed);
List<Vector3Int> terrainCoords = new List<Vector3Int>();
SMappingRanges ranges = new SMappingRanges();
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
nx = (ranges.mapx0 + ((double)x / (double)width) * (ranges.mapx1 - ranges.mapx0)) * 3;
ny = (ranges.mapy0 + ((double)y / (double)height) * (ranges.mapy1 - ranges.mapy0)) * 3;
if (combinedTerrain.Get(nx, ny) > 0f)
{
terrainCoords.Add(new Vector3Int(x, height - y, 0));
}
}
}
List<Tuple<int, int>> neighbors = new List<Tuple<int, int>>() {Tuple.Create(1, 1), Tuple.Create(-1, -1),
Tuple.Create(0, 1), Tuple.Create(1, 0),
Tuple.Create(0, -1), Tuple.Create(-1, 0),
Tuple.Create(-1, 1), Tuple.Create(1, -1)};
for (int index = 0; index < terrainCoords.Count; index++)
{
if (index == terrainCoords.Count)
{
break;
}
touchCount = 0;
for (int posAdd = 0; posAdd < neighbors.Count; posAdd++)
{
newPos = new Vector3Int(terrainCoords[index].x + neighbors[posAdd].Item1, terrainCoords[index].y + neighbors[posAdd].Item2, 0);
touchCount += terrainCoords.Contains(newPos) ? 1 : 0;
}
if (touchCount < 2)
{
terrainCoords.Remove(terrainCoords[index]);
}
}
for (int j = 0; j < caveSmoothness; j++)
{
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
if (!terrainCoords.Contains(new Vector3Int(x, y, 0)))
{
touchCount = 0;
for (int posAdd = 0; posAdd < neighbors.Count; posAdd++)
{
newPos = new Vector3Int(x + neighbors[posAdd].Item1, y + neighbors[posAdd].Item2, 0);
touchCount += terrainCoords.Contains(newPos) ? 1 : -1;
}
if (touchCount > 1)
{
terrainCoords.Add(new Vector3Int(x, y, 0));
}
}
}
}
}
foreach (Vector3Int blck in terrainCoords)
{
grid.SetTile(blck, stoneTile);
}
terrainCoords.Sort((x, y) => x.x == y.x ? x.y.CompareTo(y.y) : x.x.CompareTo(y.x));
terrainCoords.Reverse();
TileBase selectedTile;
int depth = 0;
int lastx = 0;
int lasty = terrainCoords[0].y + 1;
foreach (Vector3Int blck in terrainCoords)
{
depth = blck.x != lastx ? 0 : depth;
lasty = blck.x != lastx ? blck.y + 1 : lasty;
selectedTile = depth < 4 ? grassTile : stoneTile;
selectedTile = 3 < depth && depth < 30 ? dirtTile : selectedTile;
grid.SetTile(blck, selectedTile);
lastx = blck.x;
depth += lasty - blck.y;
lasty = blck.y;
}
int layerNum = 1;
List<Vector3Int> posList = new List<Vector3Int>();
foreach (GameObject layer in fractalLayers)
{
GetPerlinLayer component = layer.GetComponent<GetPerlinLayer>();
for (int k = 0; k < component.populateCount; k++)
{
layerNum++;
foreach (Vector3Int pos in component.GetFractalCoords(width, height, (uint)(seed * layerNum)))
if (grid.GetTile(pos) != null && grid.GetTile(pos) != grassTile)
{
grid.SetTile(pos, component.defaultTile);
}
}
}
}
public static ModuleBase CavesAndMountains(uint seed)
{
AccidentalNoise.Gradient ground_gradient = new AccidentalNoise.Gradient(0, 0, 0, 1);
// lowlands
Fractal lowland_shape_fractal = new Fractal(FractalType.BILLOW, BasisTypes.GRADIENT, InterpTypes.QUINTIC, 2, 0.25, seed);
AutoCorrect lowland_autocorrect = new AutoCorrect(lowland_shape_fractal, 0, 1);
ScaleOffset lowland_scale = new ScaleOffset(0.125, -0.45, lowland_autocorrect);
ScaleDomain lowland_y_scale = new ScaleDomain(lowland_scale, null, 0);
TranslatedDomain lowland_terrain = new TranslatedDomain(ground_gradient, null, lowland_y_scale);
// highlands
Fractal highland_shape_fractal = new Fractal(FractalType.FBM, BasisTypes.GRADIENT, InterpTypes.QUINTIC, 4, 2, seed);
AutoCorrect highland_autocorrect = new AutoCorrect(highland_shape_fractal, -1, 1);
ScaleOffset highland_scale = new ScaleOffset(0.25, 0, highland_autocorrect);
ScaleDomain highland_y_scale = new ScaleDomain(highland_scale, null, 0);
TranslatedDomain highland_terrain = new TranslatedDomain(ground_gradient, null, highland_y_scale);
// mountains
Fractal mountain_shape_fractal = new Fractal(FractalType.RIDGEDMULTI, BasisTypes.GRADIENT, InterpTypes.QUINTIC, 8, 1, seed);
AutoCorrect mountain_autocorrect = new AutoCorrect(mountain_shape_fractal, -1, 1);
ScaleOffset mountain_scale = new ScaleOffset(0.3, 0.15, mountain_autocorrect);
ScaleDomain mountain_y_scale = new ScaleDomain(mountain_scale, null, 0.15);
TranslatedDomain mountain_terrain = new TranslatedDomain(ground_gradient, null, mountain_y_scale);
// terrain
Fractal terrain_type_fractal = new Fractal(FractalType.FBM, BasisTypes.GRADIENT, InterpTypes.QUINTIC, 3, 0.125, seed);
AutoCorrect terrain_autocorrect = new AutoCorrect(terrain_type_fractal, 0, 1);
ScaleDomain terrain_type_y_scale = new ScaleDomain(terrain_autocorrect, null, 0);
AccidentalNoise.Cache terrain_type_cache = new AccidentalNoise.Cache(terrain_type_y_scale);
Select highland_mountain_select = new Select(terrain_type_cache, highland_terrain, mountain_terrain, 0.55, 0.2);
Select highland_lowland_select = new Select(terrain_type_cache, lowland_terrain, highland_mountain_select, 0.25, 0.15);
AccidentalNoise.Cache highland_lowland_select_cache = new AccidentalNoise.Cache(highland_lowland_select);
Select ground_select = new Select(highland_lowland_select_cache, 0, 1, 0.5, null);
// caves
Fractal cave_shape = new Fractal(FractalType.RIDGEDMULTI, BasisTypes.GRADIENT, InterpTypes.QUINTIC, 1, 4, seed);
Bias cave_attenuate_bias = new Bias(highland_lowland_select_cache, 0.65);
Combiner cave_shape_attenuate = new Combiner(CombinerTypes.MULT, cave_shape, cave_attenuate_bias);
Fractal cave_perturb_fractal = new Fractal(FractalType.FBM, BasisTypes.GRADIENT, InterpTypes.QUINTIC, 6, 3, seed);
ScaleOffset cave_perturb_scale = new ScaleOffset(0.5, 0, cave_perturb_fractal);
TranslatedDomain cave_perturb = new TranslatedDomain(cave_shape_attenuate, cave_perturb_scale, null);
Select cave_select = new Select(cave_perturb, 1, 0, 0.75, 0);
return new Combiner(CombinerTypes.MULT, cave_select, ground_select) as ModuleBase;
}
}
which i have so graciously borrowed and modified from the fine folks at accidental noise, and i made an empty gameobject which i attached this script to:
using UnityEngine;
using AccidentalNoise;
using System.Collections.Generic;
using UnityEngine.Tilemaps;
public class GetPerlinLayer : MonoBehaviour
{
public TileBase defaultTile;
public float threshold = 0.5f;
public int populateCount = 5;
public List<Vector3Int> GetFractalCoords(int width, int height, uint seed)
{
double nx, ny;
ModuleBase combinedTerrain = new Fractal(FractalType.FBM, BasisTypes.GRADIENT, InterpTypes.QUINTIC, 6, 2, seed);
List<Vector3Int> fractalCoords = new List<Vector3Int>();
SMappingRanges ranges = new SMappingRanges();
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
nx = (ranges.mapx0 + ((double)x / (double)width) * (ranges.mapx1 - ranges.mapx0)) * 3;
ny = (ranges.mapy0 + ((double)y / (double)height) * (ranges.mapy1 - ranges.mapy0)) * 3;
if (combinedTerrain.Get(nx, ny) > threshold)
{
fractalCoords.Add(new Vector3Int(x, height - y, 0));
}
}
}
return fractalCoords;
}
}
and i attached different colored square sprites for each of those gameobjects, and saved them as a prefab. Once i had that prefab, i attached that to the fractalLayers list in my previous script to generate ores. And although it runs fine on a lower scale, I cant run it on a larger scale. And since there's no cure-all for making code run faster (aside from refactoring, which i don't know how to do), and i probably could've made parts of my code more efficient since I'm a novice, i would really like some insight from the eyes of a professional on how to make my code run better. I know i didn't explain everything about my project but its really just a bare-bones project those are the only scripts and unique parts about it, you can just infer what i did and fill in the blanks. Any help is appreciated. And if you could give me the extra push along with some information on the subject, I would love to have some videos recommended along with your insight to guide me along this process, since i am more of a visual learner. Thank you! =)
(For reference, it took me about 4 minutes to build this, with the settings shown here.)
So apparently my word generation method was fine, just the loop I was using to smoothen the terrain took too long.

TerrainTexture missing in unityplayer

When I launch my game in the Unity player, the texture of my terrain is gone (image 1). When I launch the same scene in the editor, it looks as it should (image 2).
I add the texture with this code:
terrainData.alphamapResolution = 500;
SplatPrototype[] terrainTexture = new SplatPrototype[2];
terrainTexture[0] = new SplatPrototype();
terrainTexture[0].texture = (Texture2D)Resources.Load("MyTexture/GrassHillAlbedo");
terrainTexture[1] = new SplatPrototype();
terrainTexture[1].texture = (Texture2D)Resources.Load("MyTexture/SandAlbedo");
terrainData.splatPrototypes = terrainTexture;
float[,,] splatMapData = new float[terrainData.alphamapWidth, terrainData.alphamapHeight, 2];
for (int x = 0; x < terrainData.alphamapWidth; x++)
{
for (int y = 0; y < terrainData.alphamapHeight; y++)
{
// Grasland
if (biomes[x, y] == 0)
{
splatMapData[x, y, 0] = 1;
splatMapData[x, y, 1] = 0;
}
// Desert
if (biomes[x, y] == 1)
{
splatMapData[x, y, 0] = 0;
splatMapData[x, y, 1] = 1;
}
}
}
terrainData.SetAlphamaps(0, 0, splatMapData);
Does anyone know a solution to this problem?
The solution was to enable "write/read" on the texture.

How to create a Grid system where each square has an x and y value using visual studios graphics?

My goal is to have a robot use this grid to create a map base off the information it collects from its surroundings. When the robot detects an object the square in front of it turns red. Currently I am stuck on how I can give each square an x and Y value for location purposes. Also when I scroll the screen the block sizes change, can someone provide help with that as well?
Rectangle rect = new Rectangle(700, 350, 50, 50);
g.DrawRectangle(myPen, rect); // Draws the Rectangle to the screen
e.Graphics.FillEllipse(myBrush, 700,350,50,50);`
for (int i = 0; i < 9900; i = i + 50)
{
rect = new Rectangle(0 + i, 0, 50, 50);
g.DrawRectangle(myPen, rect);
for (int j = 0; j < 9900; j = j + 50)
{
rect = new Rectangle(0 + i, 0 + j, 50, 50);
g.DrawRectangle(myPen, rect);
}
}
Here is a very quick example of how to do this using a 2d array. It was written in LINQPad, so it may look a little odd, but it should give you some leads. It allows you to store a map and look up values using x and y coordinates. You can use the CellInfo class to add any extra information about the cell that you need, beyond if it is blocking or not.
Ideally, you would want to wrap the entire array up in your own Map class, that abstracts away the details, and gives you a lot of helpful utility functions. For instance, if your map is extremely large, you may run out of memory. You could have the Map class only load smaller blocks of the map from files on disk as needed, or even make the map wrap around its self easily.
void Main()
{
var map = new CellInfo[10, 10];
for (int x = 0; x < 10; x++)
{
for (int y = 0; y < 10; y++)
{
map[x, y] = new CellInfo();
}
}
var rnd = new Random();
for (int i = 0; i < 20; i++)
{
map[rnd.Next(0, 10), rnd.Next(0, 10)].IsBlocked = true;
}
DrawMap(map).Dump();
}
public Bitmap DrawMap(CellInfo[,] map)
{
var img = new Bitmap(320, 320, PixelFormat.Format32bppArgb);
using (var g = Graphics.FromImage(img))
{
for (int x = 0; x < 10; x++)
{
for (int y = 0; y < 10; y++)
{
var cell = map[x, y];
Brush brush = cell.IsBlocked ? Brushes.Red : Brushes.White;
g.FillRectangle(brush, x * 32, y * 32, 31, 31);
g.DrawRectangle(Pens.Black, x * 32, y * 32, 31, 31);
}
}
}
return img;
}
public class CellInfo
{
public bool IsBlocked { get; set; } = false;
}
It produces the following output (varies each time it is run):

Drawing a layered tile based map

So I'm trying to draw a layered tile based map, as the title says. I have this so far. The tiles i am using are (32, 32). It's currently drawing only 1 type of tile as the whole tile map. When it should be drawing out several different types of tiles to make a map.
for (int layers = 0; layers < map.Layers.Count; layers++) {
for (var i = 0; i < map.Layers[layers].Tiles.Count; i++) {
int gid = map.Layers[layers].Tiles[i].Gid;
if (gid != 0) {
int tileFrame = gid - 1;
int row = tileFrame / (map.Height / tileHeight);
float x = (i % map.Width) * map.TileWidth;
float y = (float)Math.Floor(i / (double)map.Width) * map.TileHeight;
Rectangle tilesetRec = new Rectangle(0, 0, 32, 32);
for (int j = 0; j < tileSets.Count; j++) {
for (int k = 0; k < tileSets[j].Tiles.Count; k++) {
spriteBatch.Draw(tileSets[j].Tiles[k].Image.Texture, new Rectangle((int)x, (int)y, 32, 32), Color.White);
}
}
}
}
}
This is not entirely my code this is someone elses that i have tried to build on apparently it worked for the person for drawing one layer. This is the original code:
for (var i = 0; i < _map.Layers[0].Tiles.Count; i++) {
int gid = _map.Layers[0].Tiles[i].Gid;
// Empty tile, do nothing
if (gid == 0) {
} else {
int tileFrame = gid - 1;
int row = tileFrame / (_tileset.Height / _tileHeight);
float x = (i % _map.Width) * _map.TileWidth;
float y = (float)Math.Floor(i / (double)_map.Width) * _map.TileHeight;
Rectangle tilesetRec = new Rectangle(_tileWidth * tileFrame, _tileHeight * row, 32, 32);
spriteBatch.Draw(_tileset, new Rectangle((int)x, (int)y, 32, 32), tilesetRec, Color.White);
}
}
Your problem is that for each tile position you seem to be drawing all tiles in all tilesets. The variables tileFrame, row and tilesetRec, which were used to render the specific tile in the original code, are not used in your first snippet.

Categories