I am trying to create a Tetris game in XNA to better learn to make a better game in the future. The only problem I am having is the 'deleting rows' functionality of the game. I have a integer matrix to hold all the rows count of the blocks in them. Whenever I create a new block, I increment the count by one in the specified row. Then, I check to see if any of the values in the matrix has met or exceeded 10. Then if it has, I delete all the blocks in said row. The problem I am having is that it's not reliable, and it doesn't keep track of the count as well as it should for some reason, and sometimes- it won't delete all the blocks in the row. If you need to see any other classes, let me know. Thanks, help is appreciated.
public class Main : Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
//Texture for the block
public static Texture2D block;
//Font
public static SpriteFont font1;
//Which shape we're dealing with(Moving)
public static int shapeIndex;
//The next shape, the one we can see previewed
public static Shape nextShape;
//The first shape we use
public static Shape s2;
//All the shapes
public static List<Shape> shapes = new List<Shape>();
//All the blocks that have stopped moving (The shapes are converted to blocks when they stop moving to make for easier deletion)
public static List<Block> blocks = new List<Block>();
//The count of blocks in each row
public static int[] rowCount = new int[20];
public Main()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
graphics.PreferredBackBufferHeight = 500;
}
protected override void Initialize()
{
this.IsMouseVisible = true;
base.Initialize();
}
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
block = Content.Load<Texture2D>("Sprites//TetrisBlock");
font1 = Content.Load<SpriteFont>("Fonts//GameFont");
//Creating a random shape
switch (new Random().Next(1, 3))
{
case 1:
nextShape = new Shape(Shape.Shapes.tShape, new Vector2(550, 0), false);
break;
case 2:
nextShape = new Shape(Shape.Shapes.lineShape, new Vector2(550, 0), false);
break;
}
//The current shape we're dealing with
shapeIndex = 0;
//Creating the first shape
s2 = new Shape(Shape.Shapes.lineShape, new Vector2(), true);
}
protected override void Update(GameTime gameTime)
{
//If the blocks that are still are rainbow, have them cycle through their colors
foreach (Block b in nextShape.Blocks)
{
if (b.RainbowBlock)
b.changeColor(gameTime);
}
//Update all the shapes
for (int i = 0; i < shapes.Count; i++)
{
shapes[i].Update(gameTime);
}
//If the shape has hit another shape and stopped moving
if (!shapes[shapeIndex].MoveDown)
{
//For every block that was in the shape, add it to the block list and increase that row's count by one
foreach (Block b in shapes[shapeIndex].Blocks)
{
blocks.Add(b);
rowCount[b.Row]++;
}
//Remove that shape
shapes.RemoveAt(shapeIndex);
//The current shape we need to move
Shape s3 = nextShape;
s3.Position = new Vector2();
s3.Imaginary = false;
shapes.Add(s3);
//Creating a new random shape for the next shape
switch (new Random().Next(1, 4))
{
case 1:
nextShape = new Shape(Shape.Shapes.tShape, new Vector2(550, 0), false);
break;
case 2:
nextShape = new Shape(Shape.Shapes.lineShape, new Vector2(550, 0), false);
break;
case 3:
nextShape = new Shape(Shape.Shapes.lShape, new Vector2(550, 0), false);
break;
}
}
//Testing whether or not rows have reached their maximum capacity
for (int i = 0; i < rowCount.Length; i++)
{
//If a row has reached its capacity
if (rowCount[i] >= 10)
{
//Remove that row
removeRow(i);
//Move all blocks that are above that row down one
foreach (Block b in blocks)
{
if (b.Row < i)
{
//Subtract the old rowcount by one
rowCount[b.Row]--;
b.Row++;
//Add one to the rowcount(If I remove this, it seems to work a little better but it still has issues)
rowCount[b.Row]++;
}
}
}
}
//Update all the blocks that are still
foreach (Block b in blocks)
b.Update(gameTime);
base.Update(gameTime);
}
//Remove the row specified in the parameters
public void removeRow(int row)
{
//For every block
for (int i = 0; i < blocks.Count; i++)
{
//See if it's in the row the user wants to remove
if (blocks[i].Row.Equals(row))
{
//If it is, remove it and decrement that row's rowcount
blocks.RemoveAt(i);
rowCount[row]--;
//Here was the problem, I wasn't decrementing i to check the next block
i--;
}
}
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin();
//Draws every shape in the game
foreach (Shape s in shapes)
s.Draw(spriteBatch);
//Draws all the blocks at the bottom that have stopped moving
foreach (Block b in blocks)
b.Draw(spriteBatch);
//Info for me
spriteBatch.DrawString(font1, "Next Block:", new Vector2(430, 0), Color.Black);
spriteBatch.DrawString(font1, rowCount[19].ToString() + " " + blocks.Count + " Blocks", new Vector2(300, 0), Color.Black);
//For the next shape, draw every block so we know what it looks like
foreach (Block b in nextShape.Blocks)
b.Draw(spriteBatch);
spriteBatch.End();
base.Draw(gameTime);
}
}
[EDIT]
The parts moving down works just fine, it's just deleting rows that troublesome. I also tried to comment as best I could, if you have any questions, just ask. Thanks again.
When I was iterating through the blocks that I was checking, if I deleted it, I didn't decrement the iteration variable to check the next block- so all the blocks weren't being checked.
Related
I am re-creating the game of cluedo and I want to map the possible paths that the player can move after dice roll.
I have mapped the grid by drawing pictureboxes and naming them to their mapped location.
Here is my code so far for the possible paths:
int Roll;
private void RollDice()
{
ResetTiles();
JimRandom Random = new JimRandom();
//Roll DIce 1
int dice1 = Random.Next(1, 7);
//Roll DIce 2
int dice2 = Random.Next(1, 7);
Roll = dice1 + dice2;
//Set Dice images
pbDice1.BackgroundImage = Roller[dice1 - 1].Picture;
pbDice2.BackgroundImage = Roller[dice2 - 1].Picture;
btnRoll.Enabled = false;
Test(Roll);
//Show available moves
Control[] lCurrent = PnlBoard.Controls.Find("pnl" + CurrentPlauer, true);
Panel Current = null;
System.Drawing.Point CurrentLoc = new System.Drawing.Point(0, 0);
foreach (Control c in lCurrent)
{
Current = c as Panel;
CurrentLoc = new System.Drawing.Point(c.Location.X, c.Location.Y);
}
//Dynamic map
List<string> possiblities = new List<string>();
int currentRow = CurrentLoc.Y / tileWidth;
int currentCol = CurrentLoc.X / tileHeight;
//Find all possible start blocks
string down = String.Format("Col={0:00}-Row={1:00}", currentCol, currentRow + 1);
string up = String.Format("Col={0:00}-Row={1:00}", currentCol, currentRow - 1);
string left = String.Format("Col={0:00}-Row={1:00}", currentCol - 1, currentRow);
string right = String.Format("Col={0:00}-Row={1:00}", currentCol + 1, currentRow);
List<string> startBlocks = new List<string>();
//See if down is available
Control[] LPossible = PnlBoard.Controls.Find(down, true);
if (LPossible.Length > 0)
{
startBlocks.Add(down);
}
//See if Up is available
LPossible = PnlBoard.Controls.Find(up, true);
if (LPossible.Length > 0)
{
startBlocks.Add(up);
}
//See if left is available
LPossible = PnlBoard.Controls.Find(left, true);
if (LPossible.Length > 0)
{
startBlocks.Add(left);
}
//See if right is available
LPossible = PnlBoard.Controls.Find(right, true);
if (LPossible.Length > 0)
{
startBlocks.Add(right);
}
//possiblilities 1
foreach (string s in startBlocks)
{
Control[] lStarBlock = PnlBoard.Controls.Find(s, true);
PictureBox startBlock = lStarBlock[0] as PictureBox;
int sRow = startBlock.Location.Y / tileWidth;
int sCol = startBlock.Location.X / tileHeight;
//Rows
for (int row = sRow; row < sRow + Roll; row++)
{
//Columns
for (int col = sCol; col < sCol + Roll; col++)
{
possiblities.Add(String.Format("Col={0:00}-Row={1:00}", col, row));
}
}
}
//Show possible moves
foreach (string p in possiblities)
{
LPossible = PnlBoard.Controls.Find(p, true);
if (LPossible.Length > 0)
{
PictureBox active = LPossible[0] as PictureBox;
active.Image = Cluedo.Properties.Resources.TileActive;
System.Threading.Thread.Sleep(1);
Application.DoEvents();
}
//else
//{
// break;
//}
}
}
There's a lot of things I would do different here. This is more of a Code Review post, but there's a solution to your problem at the end, and perhaps the rest can help you to improve the overall state of your code.
Randomness
You're creating a new random generator instance for every method call:
JimRandom Random = new JimRandom();
This often results in the same values being generated if the method is called in rapid succession. Perhaps that's why you're using a cryptographic RNG instead of a PRNG? A PRNG should be sufficient for a game like this, as long as you reuse it.
Using the right types
You're determining the current player location with the following code:
//Show available moves
Control[] lCurrent = PnlBoard.Controls.Find("pnl" + CurrentPlauer, true);
Panel Current = null;
System.Drawing.Point CurrentLoc = new System.Drawing.Point(0, 0);
foreach (Control c in lCurrent)
{
Current = c as Panel;
CurrentLoc = new System.Drawing.Point(c.Location.X, c.Location.Y);
}
It looks like CurrentPlauer is a string. Creating a Player class that stores the name and current location of a player would make things much easier:
Point currentLocation = currentPlayer.Location;
Splitting game logic from UI code
You're checking for passable tiles by doing string lookups against controls:
string down = String.Format("Col={0:00}-Row={1:00}", currentCol, currentRow + 1);
// ...
Control[] LPossible = PnlBoard.Controls.Find(down, true);
if (LPossible.Length > 0)
{
startBlocks.Add(down);
}
Normally a 2D array is used for tile maps like these, possible encapsulated in a Tilemap or Map class. This makes working with tiles more natural, as you can work in tile coordinates directly instead of having to translate between UI and tile coordinates. It also breaks up the code more cleanly into a game-logic and a UI part (the code in your post is impossible to test without UI):
// TileMap class:
public bool IsPassable(int x, int y)
{
if (x < 0 || x >= Width || y < 0 || y >= Height)
return false;
return tiles[x][y] != Tile.Wall; // enum Tile { Wall, Ballroom, DiningRoom, Hall, ... }
}
// When called from your Board code:
if (map.IsPassable(currentLocation.X, currentLocation.Y + 1))
startBlocks.Add(new Point(currentLocation.X, currentLocation.Y + 1));
Reducing repetition
As for checking all direct neighboring tiles, there's no need to repeat the same code 4 times:
// Let's make a utility function:
public static IEnumerable<Point> GetNeighboringPositions(Point position)
{
yield return new Point(position.X - 1, position.Y);
yield return new Point(position.X, position.Y - 1);
yield return new Point(position.X + 1, position.Y);
yield return new Point(position.X, position.Y + 1);
}
// In the Board code:
foreach (Point neighboringPosition in GetNeighboringPositions(currentPosition))
{
if (map.IsPassable(neighboringPosition.X, neighboringPosition.Y))
startBlocks.Add(neighboringPosition);
}
Determining valid moves
Finally, we get to the code that determines which tiles the current player can move to:
//possiblilities 1
foreach (string s in startBlocks)
{
Control[] lStarBlock = PnlBoard.Controls.Find(s, true);
PictureBox startBlock = lStarBlock[0] as PictureBox;
int sRow = startBlock.Location.Y / tileWidth;
int sCol = startBlock.Location.X / tileHeight;
//Rows
for (int row = sRow; row < sRow + Roll; row++)
{
//Columns
for (int col = sCol; col < sCol + Roll; col++)
{
possiblities.Add(String.Format("Col={0:00}-Row={1:00}", col, row));
}
}
}
What this does is checking a rectangular area, using a starting position as its top-left corner. It's doing so for up to 4 neighboring positions, so the rectangles will partially overlap each other. That's just not going to work. If the map didn't have any obstacles, something like this, combined with a Manhattan distance check, could work (if you don't forget to look to the left and upwards too). Or better, some fancy looping that checks a diamond-shaped area.
However, you've got walls to deal with, so you'll need a different approach. The player's current position is at distance 0. Its direct neighbors are at distance 1. Their neighbors are at distance 2 - except those tiles that are at a lower distance (the tiles that have already been covered). Any neighbours of tiles at distance 2 are either at distance 3, or have already been covered. Of course, wall tiles must be skipped.
So you need to keep track of what tiles have already been covered and what neighboring tiles you still need to check, until you run out of movement points. Let's wrap that up into a reusable method:
public List<Point> GetReachableTiles(Point currentPosition, int maxDistance)
{
List<Point> coveredTiles = new List<Point> { currentPosition };
List<Point> boundaryTiles = new List<Point> { currentPosition };
for (int distance = 0; distance < maxDistance; distance++)
{
List<Point> nextBoundaryTiles = new List<Point>();
foreach (Point position in boundaryTiles)
{
foreach (Point pos in GetNeighboringPositions(position))
{
// You may also want to check against other player positions, if players can block each other:
if (!coveredTiles.Contains(pos) && !boundaryTiles.Contains(pos) && map.IsPassable(pos.X, pos.Y))
{
// We found a passable tile:
coveredTiles.Add(pos);
// And we want to check its neighbors in the next 'distance' iteration, too:
nextBoundaryTiles.Add(pos);
}
}
}
// The next 'distance' iteration should check the neighbors of the current boundary tiles:
boundaryTiles = nextBoundaryTiles;
}
return coveredTiles;
}
I just started to learn XNA/MonoGame and I encountered a weird exception.
The error says: The method or operation is not implemented.
And what's even more weird that a very similar code, almost the same, works. The only difference is that the other code is run on XNA and on another computer, and my code runs on MonoGame.
The code is supposed to make an animation from a sprite sheet.
Inside of my class, Animate:
public void set_state(string name, string state)
{
this.name = name;
this.state = state;
}
public void animate(int frameIndex)
{
this.frameIndex = frameIndex;
this.animatedTexture = Game1.contentManager.Load<Texture2D>(name + '/' + state);
prepare_frames();
while (this.frameIndex > rectangles.Count )
{
frameIndex = frameIndex - rectangles.Count;
}
base.draw(animatedTexture, rectangles[frameIndex], origins[frameIndex]);
}
public void prepare_frames()
{
find_dots();
find_rectangles();
find_origins();
}
public void find_dots()
{
cols = new Color[animatedTexture.Width];
lowestRectangle = new Rectangle(0, animatedTexture.Height - 1, animatedTexture.Width, 1);
animatedTexture.GetData<Color>(0, lowestRectangle, cols, 0, animatedTexture.Width);
for (int i = 0; i < cols.Length; i++)
{
if (cols[i] == Color.Black)
{
dots.Add(new Vector2(i, animatedTexture.Height));
}
}
}
public void find_rectangles()
{
for (int i = 0; i < dots.Count-2; i+=2)
{
rectangles.Add(new Rectangle((int)dots[i].X, 0, (int)dots[i+2].X - (int)dots[i].X, animatedTexture.Height-1));
}
}
public void find_origins()
{
for (int i = 1; i < dots.Count; i++)
{
if (i%2 != 0)
{
origins.Add(dots[i]);
}
}
}
the idea behind is that there is a line of dots below the sprite sheet, with those dots i can make frames from the sprite sheet.
Here is the data of the class Animated:
#region data
Texture2D animatedTexture;
string name, state; // to determine the animated state.
Rectangle lowestRectangle; // is the rectangle of the dot's.
Color[] cols; // this array is for the colors on the dot's rectungle.
List<Vector2> dots = new List<Vector2>(); // this list is for the dot's coordinates on the dot's rectungle.
List<Rectangle> rectangles = new List<Rectangle>(); // this list is for the new rectungles, each rectungle is a diffirent frame from the sprite sheet.
List<Vector2> origins = new List<Vector2>(); // this list is for each origin point of the new retungles.
int frameIndex;
#endregion
Here is the part that summons the methods above, in the main class of the MonoGame, Game1:
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin();
if (Keyboard.GetState().IsKeyDown(Keys.Right))
{
player.set_state("moshe", "run");
player.animate(frameIndex);
frameIndex++;
}
else
player.draw();
spriteBatch.End();
base.Draw(gameTime);
}
So the error occurs in this line:
animatedTexture.GetData<Color>(0, lowestRectangle, cols, 0, animatedTexture.Width);
in the method animate in the class Animate. ( The method or operation is not implemented.) When I press the right key. Why does that happens?
Quite honestly that is a big difference, between XNA and a port of it.
A NotImplementedException does exactly what it suggest, it is thrown when a method or operation has not been implemented.
Nothing appears to be documented much about this, but it has been reported to the MonoGame bug tracker and is assigned to a developer for the 3.x release.
Using the SharpDX version however, this error does not exist.
So, I'm trying to make a small program that generates chunks, as in 2 Texture2Ds'. I Made another class called Terrain_Plains.
Constructor (you can guess I already made the variables):
public Terrain_Plains(Texture2D chunkSprite, int y)
{
chunks = chunkSprite;
this.y = y;
//Load drawRectangle
drawRectangle = new Rectangle(0, y, 50, 50);
}
Then I made a draw method:
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(chunks, drawRectangle, Color.White);
}
I made an array with the Terrain_Plains in the Game1 method:
Terrain_Plains[] terrain = new Terrain_Plains[2];
And then initialized it using a for loop.
Everything went as expected except one thing: It wasn't showing the 2nd Terrain_Plains.
How can I make them both side-by-side, without having to make another Rectangle? Reason I want to only use one Rectangle is because I want to add more than just 2 Terrain_Plains
EDIT FOR Preston Guillot:
for loop used to initialize array:
for (int i = 0; i < 2; i++)
{
terrain[i] = new Terrain_Plains(sprite, WINDOW_HEIGHT - 50);
}
for loop to draw the array:
for (int i = 0; i < 2; i++)
{
terrain[i].Draw(spriteBatch);
}
I would like to say sorry in advance for the amount of code I will post, but I can't seem to get my collision detection to work, the player and the objects pass through each other with no effect when I play test.
I receive 0 warnings or errors, but the Player playerBot object does not seem to interact with any of the level items I have imported from GLEED2D.
One thing I did was to store the values of my item's rectangles and color arrays in lists so they could be all easily iterated through, maybe this is the source of the problem.
If you can spot why my code is not working I will be hugely grateful. I have removed any code that is definitely not relevant, and I am running VS 2010 with GLEED2D 1.3 if that helps.
Thanks again.
// Item Class ImageItem Downcast
public class ImageItem : Item
{
public Texture2D Texture;
}
// Level
Level level;
// Ints
int iNumOfItems = 0;
int iTextureDataListNum = 0;
int iRectangleListNum = 0;
// Lists
List<Color []> itemTextureDataList = new List<Color[]>();
List<Rectangle> itemRectangleList = new List<Rectangle>();
protected override void Initialize()
{
if (filename.Length > 0) level = Level.FromFile(filename, Content);
else level = Level.FromFile("level1.xml", Content);
foreach (Layer layer in level.Layers)
{
foreach (Item item in layer.Items)
{
iNumOfItems =+ 1;
}
}
// Creates Player Ship
playerBot = new Player(new Vector2(400f, 240f), new Vector2(0f, 0f));
base.Initialize();
}
protected override void LoadContent()
{
Texture2D pixel = new Texture2D(GraphicsDevice, 1, 1, false, SurfaceFormat.Color);
pixel.SetData(new[] { Color.White });
spriteBatch = new SpriteBatch(GraphicsDevice);
// Player Bot
playerBot.LoadContent(Content, "Images/Player Bot Sprite Sheet", 40, 40, 4);
// Assigns level textures color data to array
foreach (Layer layer in level.Layers)
{
foreach (Item item in layer.Items)
{
ImageItem imageItem = item as ImageItem;
if (imageItem != null)
{
Texture2D texture = imageItem.Texture;
itemTextureDataList[iTextureDataListNum] = new Color[imageItem.Texture.Width * imageItem.Texture.Height];
imageItem.Texture.GetData(itemTextureDataList[iTextureDataListNum]);
iTextureDataListNum++;
}
}
}
// Creates a rectangle for every level texture
foreach (Layer layer in level.Layers)
{
foreach (Item item in layer.Items)
{
ImageItem imageItem = item as ImageItem;
if (imageItem != null)
{
itemRectangleList[iRectangleListNum] = new Rectangle((int)imageItem.Position.X, (int)imageItem.Position.Y, imageItem.Texture.Width, imageItem.Texture.Height);
iRectangleListNum++;
}
}
}
spriteBatch = new SpriteBatch(GraphicsDevice);
}
protected override void Update(GameTime gameTime)
{
// Player Update
playerBot.Update(gameTime);
((Sprite)playerBot).Update(gameTime);
// Check for player collisons with level
for (int i = 0; i < iNumOfItems - 1; i++)
{
if (IntersectPixels(playerBot.colRectangle, playerBot.textureDataArray, itemRectangleList[i], itemTextureDataList[i]) == true)
{
playerBot.StopMovement();
}
}
base.Update(gameTime);
}
// Level Collision Detection Method
static bool IntersectPixels(Rectangle rectangleA, Color[] dataA, Rectangle rectangleB, Color[] dataB)
{
// Find the bounds of the rectangle intersection
int top = Math.Max(rectangleA.Top, rectangleB.Top);
int bottom = Math.Min(rectangleA.Bottom, rectangleB.Bottom);
int left = Math.Max(rectangleA.Left, rectangleB.Left);
int right = Math.Min(rectangleA.Right, rectangleB.Right);
// Check every point within the intersection bounds
for (int y = top; y < bottom; y++)
{
for (int x = left; x < right; x++)
{
// Get the color of both pixels at this point
Color colorA = dataA[(x - rectangleA.Left) + (y - rectangleA.Top) * rectangleA.Width];
Color colorB = dataB[(x - rectangleB.Left) + (y - rectangleB.Top) * rectangleB.Width];
// If both pixels are not completely transparent
if (colorA.A != 0 && colorB.A != 0)
{
// Then an intersection has been found
return true;
}
}
}
// No intersection fond
return false;
}
// Sprite Class
public void Update(GameTime gameTime)
{
textureDataArray = new Color[texture.Width * texture.Height];
texture.GetData(textureDataArray);
// Player Class
public void StopMovement()
{
velocity.X *= -1;
velocity.Y *= -1;
}
The first thing I'll say here is, you should aim to be more Object Oriented in your approach. Storing a list of textures and a list of rectangles alongside your list of Items is "bad" technique and going to eventually cause you some massive headaches when it comes to debugging.
So first of all, instead of having a list of Color[] and a list of Rectangle, add one Color[] and one Rectangle to your ImageItem class and work with those instead, or at least create a little class called "CollisionData" that has a Rectangle and a Color[] and store those in a single list.
Secondly, note that there is a Rectangle.Intersect(Rectangle A, Rectangle B) that gets your the rectangle of intersection. So you can tidy up your code a bit by using that.
Your color checking can be simplified to (ColorA.A * ColorB.A != 0) as either being zero will
cause the result to be zero.
Regarding not getting any errors, put a breakpoint at the start of the collision checking loop. Does the application break? If yes, what is the value of iNumItems? (you can hover over it to see the current value at point of breaking). If no, then that section of code isn't being reached. Put another breakpoint a bit further back and a bit further back until it gets hit, then figure out why the code isn't executing.
I am making a simple process which will create a colour changing spiral so I can test a range of variables and learn some C#. However, though I can not find a problem in the code, when I debug it, I am returned with a blank blue screen. Can any one find the problem. Here is all the code containing the variables needed for the ball point:
Vector2 Tripos;
List<Color> Tricol;
List<Vector2> datatripos;
List<int> count;
Color currentcol;
float Tri_angle;
float Triscale;
int Tri_speed;
int screenwidth;
int screenheight;
int addtocount;
Texture2D Ball;
int colourchangespeed;
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
Tripos = new Vector2(screenwidth / 2, screenheight / 2);
Triscale = 1;
Tri_angle = 1;
Tri_speed = 1;
colourchangespeed = 1;
Ball = Content.Load<Texture2D>("ball");
currentcol = new Color(0, 0, 0);
addtocount = 0;
datatripos = new List<Vector2>();
Tricol = new List<Color>();
}
This is called by the update method:
private void Posgen()
{
Tripos.X += (float)Math.Sin(MathHelper.ToRadians(Tri_angle))*Tri_speed;
Tripos.Y += (float)Math.Cos(MathHelper.ToRadians(Tri_angle))*Tri_speed;
Tri_angle++;
}
private void colchanger()
{
currentcol.R += (byte)colourchangespeed;
if (currentcol.R == 255)
{
currentcol.R = 0;
currentcol.G += (byte)colourchangespeed;
}
if (currentcol.G == 255)
{
currentcol.G = 0;
currentcol.B += (byte)colourchangespeed;
}
if (currentcol.B == 255)
{
currentcol.B = 0;
}
}
private void dataadd()
{
addtocount++;
Tricol.Add(currentcol);
datatripos.Add(Tripos);
count.Add(addtocount);
}
Called by the draw method:
private void drawtri()
{
foreach (Vector2 data in datatripos)
{
spriteBatch.Draw(Ball, data, null, currentcol, 0, new Vector2(5, 5), Triscale, SpriteEffects.None, 0);
}
}
If you want the full code ask in advance. There are some variables I don't use but I intend to use for later so ignore these.
Thanks in advance.
Yours Mona.
Check that you are calling dataadd().
As a precaution, colourchangespeed should be declared as a byte rather than as an int because you're only casting to a byte anyway. When checking you colour values, the current value should be compared as >= 255 in the case that colourchangespeed is not 1.
A tip to writing good questions: Remove everything that's unrelated. Everything.