XNA Confusion about 2d Rectangle arrays - c#

I'm making a tiled strategy game alhoug it doesn't even resemble that in complexity. however, I ran into something i can't figure out myself. it should make the tile a click red and if i click it again it should make it normal again. but what it does is: in the first 4 or so tiles it makes everythinng red on the opposide sideflipped verticly,, but that should be fixable by reversing and x and y value. however after the fourth tile everything just get's placed on a random place(or as it seems atleast).i really can't figure it out myself and i have rewritten it from scratch 3 times already. I would be really thankfull if a more experienced (or less experienced is also okay) programmer could point me to my problem
My code(chopped up in chunks of releveance ):
protected override void LoadContent()
{
baseLayer.LoadContent("TextFile1.txt");
standardTexture = Content.Load<Texture2D>("Tiles/Grass/GrassTile1");
selectRects = new Rectangle[(int)baseLayer.MapDimensions.X, (int)baseLayer.MapDimensions.Y];
while (j<baseLayer.MapDimensions.Y)
{
while (i < baseLayer.MapDimensions.X)
{
selectRects[i, j] = new Rectangle(i * standardTexture.Width, j * standardTexture.Height,
standardTexture.Width, standardTexture.Height);
i++;
}
i = 0;
j++;
}
j = 0;
}
protected override void Update(GameTime gameTime)
{
while(j<baseLayer.MapDimensions.Y)
{
while(i<baseLayer.MapDimensions.X)
{
if (standardCheck.Click(selectRects[i, j], mouseState, prevMouseState))
{
if (colorArray[i, j] != Color.White)
colorArray[i, j] = Color.White;
else
colorArray[i, j] = Color.Red;
}
i++;
}
i = 0;
j++;
}
j = 0;
and my main drawing class(a litle bigger):
public class LoadMap
{
{
get { return map; }
set { map = value; }
}
public Vector2 MapDimensions
{
get { return dimensions; }
set { dimensions = value; }
}
public LoadMap()
{
lineindex = 0;
}
public void Draw(SpriteBatch spriteBatch, Texture2D[] maptexture,Color[,] color)
{
for (int i = 0; i < dimensions.X; i++)
{
for (int j = 0; j < dimensions.Y; j++)
{
if (map[i, j] == 1)
{
spriteBatch.Draw(maptexture[0],
new Vector2(j * maptexture[0].Width, i * maptexture[0].Height), color[i,j]);
}
if (map[i, j] == 2)
{
spriteBatch.Draw(maptexture[1],
new Vector2(j * maptexture[0].Width, i * maptexture[0].Height), color[i, j]);
}
if (map[i, j] == 3)
{
spriteBatch.Draw(maptexture[2],
new Vector2(j * maptexture[0].Width, i * maptexture[0].Height), color[i, j]);
}
}

Related

modified Texture2D not showing up

So I am trying to make 2 different texture2d's from 1. basically by cutting it in half. I tried a simple way, but it is kinda slow and right now ddoesn't work at all.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace MediaPipe.HandPose
{
public sealed class camerasplitter : MonoBehaviour
{
public WebcamInput main, first, second;
public Texture2D camdata,firsttex,secondtex;
public int frame = 0;
// Start is called before the first frame update
void Start()
{
firsttex = new Texture2D(1080, 960);
secondtex = new Texture2D(1080, 960);
first._dummyImage = firsttex;
second._dummyImage = secondtex;
}
// Update is called once per frame
void Update()
{
frame++;
if (frame > 1000) frame = 1;
if (frame % 3 == 0)
{
camdata =toTexture2D(main.Texture);
for (int i = 0; i < camdata.height; i++)
{
for (int j = 0; j < camdata.width/2; j++)
{
firsttex.SetPixel(i, j, camdata.GetPixel(i, j));
secondtex.SetPixel(i, j + camdata.width / 2, camdata.GetPixel(i, j + camdata.width / 2));
}
}
firsttex.Apply(false);
/*for (int i = 0; i < camdata.height; i++)
{
for (int j = camdata.width / 2; j < camdata.width; j++)
{
secondtex.SetPixel(i, j, camdata.GetPixel(i, j));
}
}*/
secondtex.Apply(false);
}
}
public Texture2D toTexture2D(Texture rTex)
{
Texture2D dest = new Texture2D(rTex.width, rTex.height, TextureFormat.RGBA32, false);
Graphics.CopyTexture(rTex, dest);
return dest;
}
}
}
when i run it, the camdata is getting data from other script and it shows. but firsttex and secondtex are not showing. they are gray. even if it lags to do the "for" operation.
thats the thing that is stopping my project. Thanks in advance!

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);
}
}

Trying center a tower on tilemap

Iam making a placement system using tilemaps, its almost done but have a small problem.
Placement System
As you can see the tower never be on middle of tiles, i want it always be on middle, even if the size is 2x2 (on that video is 3x3), i dont know what is wrong with my code, so i need help.
void Update()
{
Vector3 mousePosWorldPoint = Camera.main.ScreenToWorldPoint(Input.mousePosition);
Vector3Int cellPos = sniperTower.World.MapGrid.LocalToCell(mousePosWorldPoint);
Vector3 posConverted = sniperTower.World.MapGrid.CellToLocalInterpolated(cellPos);
BoundsInt bounds = new BoundsInt();
bounds.position = cellPos;
bounds.size = sniperTower.BuldingSize;
if (sniperTower.PreviousBounds.position != null && sniperTower.PreviousBounds.position != bounds.position) {
sniperTower.World.clearTiles(sniperTower.PreviousBounds);
sniperTower.Moving(bounds,new Vector3(posConverted.x, posConverted.y, 10));
sniperTower.World.fillTiles("Placing",bounds);
}else if(sniperTower.PreviousBounds.position == null) {
sniperTower.Moving(bounds,new Vector3(posConverted.x, posConverted.y, 10));
sniperTower.World.fillTiles("Placing",bounds);
}
}
//The Moving Method
public virtual void Moving(BoundsInt bounds,Vector3 position){
this.movingBounds = bounds;
this.previousBounds = this.movingBounds;
this.buildingObject.transform.position = position;
}
//The FillTiles and ClearTiles Methods
public void fillTiles(string tileType, BoundsInt area){
for (int x = area.x; x < (area.x + area.size.x); x++) {
for (int y = area.y; y < (area.y + area.size.y); y++) {
placingTilemap.SetTile(new Vector3Int(x,y,0),tiles[tileType]);
}
}
}
public void clearTiles(BoundsInt area){
for (int x = area.x; x < (area.x + area.size.x); x++) {
for (int y = area.y; y < (area.y + area.size.y); y++) {
placingTilemap.SetTile(new Vector3Int(x,y,0),null);
}
}
}

Drawing polygon

I want to realize method "Draw" of class Polygon
I have WindForms project, form, and the pictureBox1,
I want that "Draw" drawing polygon in pictureBox1 and I have opportunity to move image
I don't konw how to realize it. Help, please.
public class Polygon
{
public Point[] vertexes { get; protected set; }
public Polygon(params int[] vertex)
{
if (vertex == null || vertex.Length <= 2)
throw new Exception("someText");
if (vertex.Length % 2 != 0)
throw new Exception("someText");
vertexes = new Point[vertex.Length / 2];
ColorContour = System.Drawing.Color.DarkRed;
Priming = false;
for (int i = 0, j = 0; i < vertexes.Length; i++, j += 2)
vertexes[i] = new Point(vertex[j], vertex[j + 1]);
vertexes = Point.Sort(vertexes);
if (vertexes == null || vertexes.Length <= 2)
throw new Exception("someText");
}
public double Perimetr
{
get
{
double res = 0;
for (int i = 1; i < vertexes.Length; i++)
res += Point.Length(vertexes[i - 1], vertexes[i]);
return res;
}
}
public override void Move(int deltax, int deltay)
{
vertexes[0].x = deltax;
vertexes[0].y = deltay;
for (int i = 1; i < vertexes.Length; i++)
{
vertexes[i].x -= deltax;
vertexes[i].y -= deltay;
}
}
public void Zoom(double size)
{
if (size == 0)
return;
Point firstP = new Point(vertexes[0].x, vertexes[0].y);
Point Center = Point.CentrMass(vertexes);
for (int i = 0; i < vertexes.Length; ++i)
{
vertexes[i].x = Convert.ToInt32(size * (vertexes[i].x - Center.x) + Center.x);
vertexes[i].y = Convert.ToInt32(size * (vertexes[i].y - Center.y) + Center.y);
}
Move(firstP.x, firstP.y);
}
public void Draw( ??)
{
**????**
}
publicabstract double Square { get; }
You need to take in a System.Drawing.Graphics as a parameter, and call Graphics.DrawPolygon() function. Then in the picturebox, override or implement the OnPaint() event, and call your draw function with the Graphics you receive as a parameter (child of the eventargs) in OnPaint().

Can't work out why the square won't animate across the grid

I cannot for the life of me work out how to get the block that is supposed to be drawn with every loop through the array of "Arxl" objects to animate across the grid.
Any suggestions would be really appreciated, not looking for someone to complete the code for me. just a fresh set of eyes.
public partial class Game : Form
{
//attributes
private Bitmap _grid;
private Arxl[,] _cartesianGrid;
private int _arxlAmount;
const int ARXL = 4;
public Game()
{
InitializeComponent();
_arxlAmount = (gridPictureBox.Height / ARXL);//in case height/arxl is not an even number?
_cartesianGrid = new Arxl[_arxlAmount, _arxlAmount];
_grid = new Bitmap(gridPictureBox.Width, gridPictureBox.Height);
int x;
int y;
for (x = 0; x < _arxlAmount; x++)
{
for (y = 0; y < _arxlAmount; y++)
{
_cartesianGrid[x, y] = new Arxl();
}
}
SetSeed(_cartesianGrid);
}
private void SetSeed(Arxl[,] cartesianGrid)
{
_cartesianGrid[1, 1].Active = true;
}
private void DrawArxl(Bitmap _grid, Arxl[,] cartesianGrid,int arxlAmount)
{
int x, y;
x=0;
y=0;
Graphics graphics = Graphics.FromImage(_grid);
graphics.Clear(Color.White);
for (x = 1; x < arxlAmount;x++ )
{
for (y = 1; y < arxlAmount; y++)
{
if (cartesianGrid[x, y].Active==true)
{
cartesianGrid[x, y].Area = new Rectangle(x * ARXL, y * ARXL, ARXL, ARXL);
graphics.FillRectangle(Brushes.Black, cartesianGrid[x, y].Area);
}
else if(cartesianGrid[x,y].Active==false)
{
Pen newPen=new Pen(Color.Black);
cartesianGrid[x, y].Area = new Rectangle(x * ARXL, y * ARXL, ARXL, ARXL);
graphics.DrawRectangle(newPen,cartesianGrid[x, y].Area);
newPen.Dispose();
}
}
}
}
private void timer_Tick(object sender, EventArgs e)
{
//GameOfLife(_cartesianGrid, _arxlAmount);
ScrollBlock(_cartesianGrid, _arxlAmount);
DrawArxl(_grid, _cartesianGrid, _arxlAmount);
gridPictureBox.Image = _grid;
}
private void ScrollBlock(Arxl[,] cartesianGrid, int arxlAmount)
{
int x = 0;
int y = 0;
for (x = 0; x < arxlAmount; x++)
{
for (y = 0; y < arxlAmount; y++)
{
if (_cartesianGrid[x, y].Active == true)
{
if (x>=0)
{
if (x == (arxlAmount-1))
{
_cartesianGrid[x, y].Active = false;
_cartesianGrid[1, y].Active = true;
}
else if(x<(arxlAmount-1))
{
_cartesianGrid[x, y].Active = false;
_cartesianGrid[x+1, y].Active = true;
}
}
}
}
}
}
According to a comment in your code, you want to program the life game. It will not work, if you change the cells in place, because you will have to compute the new state from the unchanged old state. Therefore, you will need to have two game boards, one with the current state and one with the new state. Instead of creating new board all the time, it is better to have two boards and to swap them. In addition, there is no point in storing the Rectangles in the board. Therefore, I declare the boards as Boolean matrix.
const int CellSize = 4;
private int _boardSize;
private bool[,] _activeBoard, _inactiveBoard;
Bitmap _grid;
The form constructor is changed like this
public Game()
{
InitializeComponent();
_boardSize = Math.Min(gridPictureBox.Width, gridPictureBox.Height) / CellSize;
_grid = new Bitmap(gridPictureBox.Width, gridPictureBox.Height);
_activeBoard = new bool[_boardSize, _boardSize];
_inactiveBoard = new bool[_boardSize, _boardSize];
SetSeed();
}
We initialize the game like this (as an example)
private void SetSeed()
{
_activeBoard[0, 0] = true;
_activeBoard[7, 4] = true;
DrawGrid();
}
The timer tick does this
ScrollBlock();
DrawGrid();
The logic in ScrollBlock is completely new. We look at the state on the _activeBoard and set the state of _inactiveBoard. Then we swap the two boards.
private void ScrollBlock()
{
for (int x = 0; x < _boardSize; x++) {
for (int y = 0; y < _boardSize; y++) {
if (_activeBoard[x, y]) {
_activeBoard[x, y] = false;
int newX = x + 1;
int newY = y;
if (newX == _boardSize) {
newX = 0;
newY = (newY + 1) % _boardSize;
}
_inactiveBoard[newX, newY] = true;
}
}
}
SwapBoards();
}
The boards are simply swapped like this
private void SwapBoards()
{
bool[,] tmp = _activeBoard;
_activeBoard = _inactiveBoard;
_inactiveBoard = tmp;
}
And finally DrawGrid draws the _activeBoard
private void DrawGrid()
{
Graphics graphics = Graphics.FromImage(_grid);
graphics.Clear(Color.White);
for (int x = 0; x < _boardSize; x++) {
for (int y = 0; y < _boardSize; y++) {
var rect = new Rectangle(x * CellSize, y * CellSize, CellSize, CellSize);
if (_activeBoard[x, y]) {
graphics.FillRectangle(Brushes.Black, rect);
} else {
graphics.DrawRectangle(Pens.Black, rect);
}
}
}
gridPictureBox.Image = _grid;
}
I've spotted your problem.
The problem is that you're updating a cell position (moving it to the right in this particular initial state), but the next iteration in the for loop finds the updated state from the previous iteration, so it updates the cell again, and again, and when the cycle stops, the cell was scrolled over to its initial cell position!, with no repainting in between.
I'm modifying your code to add an UpdateList that will turn on cells that need to be ON after the grid scan has finished to avoid updating the same "active dot" more than once. This should show a moving dot from left to right.
private void ScrollBlock(Arxl[,] cartesianGrid, int arxlAmount) {
int x = 0;
int y = 0;
List<Point> updateList = new List<Point>();
for( x = 0; x < arxlAmount; x++ ) {
for( y = 0; y < arxlAmount; y++ ) {
if( _cartesianGrid[x, y].Active == true ) {
if( x >= 0 ) {
if( x == (arxlAmount - 1) ) {
_cartesianGrid[x, y].Active = false;
//_cartesianGrid[1, y].Active = true;
updateList.Add(new Point(1, y));
} else if( x < (arxlAmount - 1) ) {
_cartesianGrid[x, y].Active = false;
//_cartesianGrid[x + 1, y].Active = true;
updateList.Add(new Point(x + 1, y));
}
}
}
}
}
foreach( var pt in updateList ) {
_cartesianGrid[pt.X, pt.Y].Active = true;
}
}
In your timer try calling gridPictureBox.Invalidate() after you assign the image to the picturebox. This will force the picturebox to redraw itself.

Categories