I am designing a space invaders game and I need to make the barriers break from where they were hit like the original game, As of now my barrier just shrinks:
for (int r = 0; r < BarrierXPos.Count; r++) {
if (CollisionCheck("Barrier", BarrierXPos[r], BarrierYPos[r], null) == true)
{
BarrierFactor[r] += 1;
}
}
for (int x = 0; x < BarrierXPos.Count; x++)
{
e.Graphics.FillRectangle(Brushes.White, (int)BarrierXPos[x], (int)BarrierYPos[x], 100 - (10 * BarrierFactor[x]), 50);
}
So as of now the size is determined by the amount of times the block has been hit. However I want it to be more like the original space invaders and would like the block to be dynamically broken from where it was hit. What I am wondering is how I can determine the pixels in which the bullet hits the barrier bitmap and subsequently remove them.
Related
i have somewhat implemented marching cubes in unity/c# (you dont need to know unity to help me though) and i cant stop feeling like i have made a big mistake in my code because it is so slow. i am already running it on a separate thread but it just takes ages to complete. please help me optimize my code.
private void _UpdateChunk()
{
lock (this)
{
// clear the tri, vert and uv lists
ClearMeshData();
// Loop through each "cube" in the terrain.
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
for (int z = 0; z < width; z++)
{
// Create an array of floats representing each corner of a cube and get the value from our terrainMap.
float[] cube = new float[8];
float[] strengths = new float[8];
for (int i = 0; i < 8; i++)
{
Vector3Int corner = new Vector3Int(x, y, z) + gamedata.CornerTable[i];
cube[i] = terrainMap[corner.x, corner.y, corner.z].BlockType;
strengths[i] = terrainMap[corner.x, corner.y, corner.z].Strength;
}
// Pass the value into the MarchCube function.
MarchCube(new Vector3(x, y, z), cube, strengths);
}
}
}
}
}
void MarchCube(Vector3 position, float[] cube, float[] strengths)
{
// Get the configuration index of this cube.
int configIndex = GetCubeConfiguration(cube);
// If the configuration of this cube is 0 or 255 (completely inside the terrain or completely outside of it) we don't need to do anything.
if (configIndex == 0 || configIndex == 255)
return;
// Loop through the triangles. There are never more than 5 triangles to a cube and only three vertices to a triangle.
int edgeIndex = 0;
Vector3 vert1 = new Vector3();
Vector3 vert2 = new Vector3();
float vert1sample = 0;
float vert2sample = 0;
float lerp = 0;
int indice = 0;
for (int i = 0; i < 5; i++)
{
for (int p = 0; p < 3; p++)
{
// Get the current indice. We increment triangleIndex through each loop.
indice = gamedata.TriangleTable[configIndex, edgeIndex];
// If the current edgeIndex is -1, there are no more indices and we can exit the function.
if (indice == -1)
return;
// Get the vertices for the start and end of this edge.
vert1 = position + gamedata.EdgeTable[indice, 0];
vert2 = position + gamedata.EdgeTable[indice, 1];
vert1sample = strengths[gamedata.EdgeIndexTable[indice, 0]];
vert2sample = strengths[gamedata.EdgeIndexTable[indice, 1]];
// Get the midpoint of this edge.
lerp = Mathf.Abs(vert1sample) / (Mathf.Abs(vert2sample) + Mathf.Abs(vert1sample));
Vector3 vertPosition = Vector3.Lerp(vert1, vert2, lerp);
// Add to our vertices and triangles list and incremement the edgeIndex.
vertices.Add(vertPosition);
triangles.Add(vertices.Count - 1);
if (getChunkVoxel(vert1 + chunkPosition) != 0)
{
uvs.Add(new Vector2(getChunkVoxel(vert1 + chunkPosition) - 1, 0));
}
else
{
uvs.Add(new Vector2(getChunkVoxel(vert2 + chunkPosition) - 1, getChunkVoxel(vert2 + chunkPosition) - 1));
}
edgeIndex++;
}
}
}
int GetCubeConfiguration(float[] cube)
{
// Starting with a configuration of zero, loop through each point in the cube and check if it is below the terrain surface.
int configurationIndex = 0;
for (int i = 0; i < 8; i++)
{
// If it is, use bit-magic to the set the corresponding bit to 1. So if only the 3rd point in the cube was below
// the surface, the bit would look like 00100000, which represents the integer value 32.
if (cube[i] < terrainSurface)
configurationIndex |= 1 << i;
}
return configurationIndex;
}
it appears that this is the part that slows my game down, help would be appreciated
i already made it faster by changing terrainpoint from a class to a struct but it is still very slow.
One main reason it is slow is that there is a lot of allocations in the loop putting a lot of pressure on the garbadge collector. There is currently 11 allocation per "cube" in the terrain in _UpdateChunk and up to 17 in MarchCube (possibly even more if the expressions like position + gamedata.EdgeTable[indice, 0] allocates a new vector). This is not reasonable. Many allocation are not needed. For example cube and strengths can be preallocated once for all the cubes in the beginning of _UpdateChunk. You do not need to allocate the vector in the expression to compute corner: you can just compute the components separately manually (or you can possibly preallocate the vector and reset its component when needed). The same thing applies for the new Vector3(x, y, z) can can be preallocated and set in the loop. Such an algorithm is computationally intensive so you should get away any overhead like virtual method calls and allocations/GC -- only low-level arrays accesses and mathematical operations should remains.
Note that some computations can be optimized. For example GetCubeConfiguration can be modified so to be branchless. Mathf.Abs(vert1sample) can be precomputed so not to compute it twice (though the compiler may already do that). I am also wondering if the expression like vertices.Add are efficient but this is dependent of the type of container which is not provided here.
I am trying to make a system that uses a perlin noise field to generate random positions that are then saved, or saved as the are generated, to a list. Then using that list the game will use those positions to spawn in objects within the level. I think that I might be on the right track, but I might have a few things in the wrong places.
Here is a link to an image of all the things that I think are relevant:
the blue dots should be the saved locations that are added to the list. But i am only getting one position 5 times, which is the correct number of positions but they are all the same position that is the problem.
// --- Random Generation of Objects --- //
Color[] colourMap = new Color[mapWidth * mapHeight];
for(int y = 0; y < mapHeight; y++) {
for(int x = 0; x < mapWidth; x++) {
float currentHeight = noiseMap[x, y];
for(int i = 0; i < regions.Length; i++) {
// --- Random Gen of Asteroids --- //
if(currentHeight <= regions[i].height) {
colourMap[y * mapWidth + x] = regions[i].colour;
Vector3 ping = new Vector3(x, 0, y);
asteroids.Add(ping);
Debug.Log(asteroids[i]);
break;
}
}
}
}
Anyway thank you for the help and reading this far, please let me know if you need anything more.
lets say that i have this image:
http://srv2.jpg.co.il/9/51c614f7c280e.png
i want to get the white ball position(x,y),
this is a verey big image, then i cut the image by rectangle.(because when the image is smaller everything is faster),
the results:
http://srv2.jpg.co.il/1/51c616787a3fa.png
now i want to track the white ball position by his color(white=rbg(255,255,255)),
my code:
Public Function GetBallPosition(ByRef HaxScreenOnly As Bitmap) As Point
For y = 0 To HaxScreenOnly.Height - 1
For x = 0 To HaxScreenOnly.Width - 1
If HaxScreenOnly.GetPixel(x, y) = Color.FromArgb(0, 0, 0) Then
If HaxScreenOnly.GetPixel(x + 8, y) = Color.FromArgb(0, 0, 0) And HaxScreenOnly.GetPixel(x + 8, y + 3) = Color.FromArgb(255, 255, 255) Then
Return New Point(x, y)
End If
End If
Next
Next
Return New Point(0, 0)
End Function
If the color of the current pixel is black and the color of the current pixel(x+8,y+3) is white then this is the ball
it's working...but its verey slow, something like 200 miliseconds to track the ball position.
this is not fast enough.
there is faster way to track the white ball(C# or VB.net)?
Finally, I have you a solution for you. Calling GetPixel is a costly process, but you use Bitmap.LockBits and manipulate / access the image data from a pointer. I took the LockBitmap class from this article.
I checked on the performance from what I was getting previously, which was exactly like you mentioned, around 200ms~.
Here is a picture of the result using LockBitmap, rescanning the image continuously with the optimized code!
static void Main(string[] args)
{
byte[] data = new WebClient().DownloadData("http://srv2.jpg.co.il/1/51c616787a3fa.png");
Image image = Image.FromStream(new MemoryStream(data));
LockBitmap bitmap = new LockBitmap(new Bitmap(image));
// this essentially copies the data into memory and copies from a pointer to an array
bitmap.LockBits();
Color black = Color.FromArgb(0, 0, 0);
Color white = Color.FromArgb(255, 255, 255);
Stopwatch stopwatch = Stopwatch.StartNew();
for (int y = 0; y < bitmap.Height; y++)
{
for (int x = 0; x < bitmap.Width; x++)
{
// GetPixel is a nice abstraction the author in the Article created so we don't have to do any of the gritty stuff.
if (bitmap.GetPixel(x, y) == black)
{
if (bitmap.GetPixel(x + 8, y) == black && bitmap.GetPixel(x + 8, y + 3) == white)
{
Console.WriteLine("White Ball Found in {0}", stopwatch.Elapsed.ToString());
break;
}
}
}
}
bitmap.UnlockBits(); // copies the data from the array back to the original pointer
Console.Read();
}
Hope this helps, it was certainly an interesting read for me.
Update:
As mentioned by King, I was able to further reduce the timing for you based on the algorithm improvement. So we've gone from O(n) to O(n log) time complexity (I think).
for (int y = 0; y < bitmap.Height; y += 3) // As we know the radius of the ball
{
for (int x = 0; x < bitmap.Width; x += 3) // We can increase this
{
if (bitmap.GetPixel(x, y) == black && bitmap.GetPixel(x, y + 3) == white)
{
Console.WriteLine("White Ball Found ({0},{1}) in {2}", x, y, stopwatch.Elapsed.ToString());
break;
}
}
}
I have some problems on the display of my model with texture.
Everything works perfectly, however, I use a loop to repeat the texture to represent a floor 20 X 20 on the screen. My texture is repeated correctly. But I do not understand why all my textures generate a flicker ...
I noticed that images are superimposed on each other. I'm sure I checked my loop is coded correctly.
see screenshot:
my code (loop function generation ground):
//Function draw - ground land
private void draw_groundLand(Vector3 position_model_origin)
{
//example generation mode 4x4 cubes
int[,,] MatriceWorldCube = new int[1,2,2];
MatriceWorldCube[0, 0, 0] = 1;
MatriceWorldCube[0, 0, 1] = 1;
MatriceWorldCube[0, 1, 0] = 2;
MatriceWorldCube[0, 1, 1] = 1;
int height = MatriceWorldCube.GetLength(0);
int width = MatriceWorldCube.GetLength(1);
int length = MatriceWorldCube.GetLength(2);
Vector3 pos_reference = position_model_origin;
for (int thickness = 0; thickness < height; thickness ++)
{
for (int column = 0; column < width; column ++)
{
for (int line = 0; line < length ; line ++)
{
// Copy any parent transforms.
Matrix[] transforms = new Matrix[model_ground_land1.Bones.Count];
model_ground_land1.CopyAbsoluteBoneTransformsTo(transforms);
// Draw the model. A model can have multiple meshes, so loop.
foreach (ModelMesh mesh in model_ground_land1.Meshes)
{
// This is where the mesh orientation is set, as well
// as our camera and projection.
foreach (BasicEffect effect in mesh.Effects)
{
effect.EnableDefaultLighting();
effect.World = transforms[mesh.ParentBone.Index] *
Matrix.CreateRotationY(cubeGroundLand1_modelRotation) * Matrix.CreateTranslation(position_model_origin);
effect.View = View;
effect.Projection = Projection;
}
// Draw the mesh, using the effects set above.
mesh.Draw();
}
position_model_origin.X = (float)(line +1);
}
position_model_origin.X = pos_reference.X;
position_model_origin.Z = (float)(column +1);
}
position_model_origin.Z = pos_reference.Z;
position_model_origin.Y = (float)(thickness+1);
}
position_model_origin.Y = pos_reference.Y;
position_model_origin = pos_reference;
}
Thank you in advance for your help. I lose patience (over a whole weekend ^ ^)
It's Z-fighting. Z-buffer precision falling with distance so far objects have more "flickers" GPU can't figure out which polygon is on top because tail of the z-buffer value isn't precise enough to distinguish 2 almost equal values.
You have 6 ways to fix it:
Move geometry or do not display part that is below.
Use something like polygon offset in OpenGL
Use CPU z-sorting instead of z-buffer.
Use only one object with 2 textures instead of 2 objects + some shaders (i don't know what exactly you are trying to achieve)
Use larger z-buffer.
Move clip planes closer to each other it will increase precision.
I have an array of pixels which make up a 2D grid and I want to move these pixels right and left over time... constantly however the loop I came up with is fairly inefficient and does not allow for much expansion in terms of changing the motion. Any ideas on how to improve what I already have would be much appreciated.
while (true)
{
for (float i = 0; i < x; i++)
{
foreach (Pixel p in pixels)
{
p.move(10, 0);
}
}
for (float i = 0; i < x * 2; i++)
{
foreach (Pixel p in pixels)
{
p.move(-10, 0);
}
}
for (float i = 0; i < x; i++)
{
foreach (Pixel p in pixels)
{
p.move(10, 0);
}
}
}
Edit: Sorry had an error in the code the middle loop needed to be -10 the first for loop moves all the pixels right, the second moves them back to the origin and then to the left, the third loop then moves them back to the origin.
You could employ an offset variable to be used in the code where pixels are actually used. Moving pixels around is then done by changing offset, which is one line of code.
Can't you just use a single loop and using int? Three loops seems to be redundant
Use one loop from 0 to x*2 and perform the movement choosing on the x value
Something like
for(int i = 0; i < x * 2; i++)
{
foreach(Pixel p in pixels)
{
if (i < x)
{
p.move(0.1, 0);
p.move(10, 0);
p.move(10, 0);
}
else
p.move(10,0)
}
}