HashSet remove element upon condition - hashset

I have a HashSet containing tens of thousands of rectangles, when the Y is less than 0 I want to remove it from the HashSet
right now my code looks like the following
for (Rectangle p : point) {
if(p.y<0){
point.remove(p);
System.out.println("removing p");
continue;
}
Here is the code for my HashSet
public HashSet<Rectangle> point;
it never removes the Rectangle that has a Y less than 0 but the System.out.println("removing p"); runs.

The problem is HashSet does not allow you to remove items that had their hash changed. So it is pretty much useless for changing items. Instead use the Array class built in libGDX and it will work fine. Not sure of the performance though maybe someone can post an answer with faster performance.

Related

What's a more efficient way to do collisions?

Here's my dilemma
I have 4 walls around the stage of my game, when a player hits these walls I do not want to make an if statement for each and every one of the walls checking if the player is hitting it, so I have created an array to hold the walls, then check if the player is hitting that. Now, because I am doing this I will not know what the player is actually hitting if he hits something, and I cannot do a check in my array if he's hitting like [0], [1], [2] etc because then I'm back to doing the checks if he's hitting specific walls. The reason I don't want to do that is for the future, when I add more barriers, buildings, and so on.
So my question is, how can I do collision checks, without hard coding checks on specific objects, and giving some sort of value that can be used for the player to respond to, for example if your hitting the top wall and you can figure that out somehow without doing the above, then make it so you can't walk through or something,
if (main.playerPosKeeper_mc.hitTestObject(this[main.StageCollisions]))
{
trace("hit");
}
StageCollisions is an array which contains all of my barriers in it.
When the player hits anything in StageCollisions, I cannot just simply subtract from his y value, or x value, because I do not know which object he hit, but I also do not want to hard code it so that I check if I'm hitting lets say the top barrier, because then why do an array in the first place if I'm just going back to making static if else statements.
^^ Refrencing this topic
AS3 - How to Cycle States of Character Animations (moving & stopped)
This has been stumping me for a little while, so help would be greatly appreciated. It is a hard question to form so I can clarify points if necessary.
So my question is, how can I do collision checks, without hard coding
checks on specific objects, and giving some sort of value that can be
used for the player to respond to, for example if your hitting the top
wall and you can figure that out somehow without doing the above, then
make it so you can't walk through or something
Right, so you want a way to perform a generic collision response. This can be a big topic. The simplest approach is usually to check for a collision after a move, then reverse the move if there's a collision.
Something like this:
function movePlayer(movementX:Number, movementY:Number):void {
var originalX:Number = player.x;
var originalY:Number = player.y;
player.x += movementX;
if (checkCollision()) {
player.x = originalX;
}
player.y += movementY;
if (checkCollision()) {
player.y = originalY;
}
}
function checkCollision():Boolean {
for each (var wall:MovieClip in walls) {
if (player.hitTestObject(wall)) {
return true;
}
}
return false;
}
This way you could have checkCollision() check 4 walls or 50 walls, it doesn't matter. It won't let the player move into them.
This is just a starting point and there are many ways it can break down or be refined.
Some trivial pseudo code for you to study:
private function collisionCheck(h:Sprite):Sprite{ // pass the hero Sprite into this function and it will return the wall that it hit
for each (b:Sprite in blockArray){ // if your array of hit-able objects is called "blockArray"
if (h.hitTtestObject(b)){ // check the hero Sprite against all objects in the array
return b;
}
}
return null;
}
Then, elsewhere in your code (maybe in your gameTick function or gameLoop function or wherever you have your game logic repeating on each frame:
private function gameTick():void{
var objectHit:Sprite = collisionCheck(_myHero); // this will run the collision check function, and return the sprite that the hero collides with;
if (objectHit != null){
objectHit.alpha = 0.5;
// this will give you a visible representation that your code is indeed working, or not.
}
}
For those moments when your hero isn't colliding with anything, this function will return null. That's why I first check if objectHit is not null before trying to perform an operation on its alpha value. Of course, you will do something other than change its alpha value in your project, but this is something I often do (with the alpha) to quickly get a visual confirmation that things are detecting what they are supposed to.

Array Based Implementation of a Vector

Homework Assistance
Describe an array based implementation of a vector such that inserting and
removing at beginning and end of the vector can be done in constant time. Argue
convincingly.
Obviously this is impossible with a straight-up array. If you remove from the front, there will be a hole that needs to be filled in order to maintain the vector property. Of course, if we grab the next element over, we will need to do this n times, so the runtime will be linear, not constant.
Another way would be to grab the last element and stick it in the front, but what good is a data structure that scrambles your data?
What I have done so far is to create an array. The odd number indices are behind some point in the array (preferably the middle for size purposes, but it can be anywhere), then the even number indices are before that point. That takes up a whole bunch of memory and has lots of open slots if that special point is not the centre point. Worst case being 2n. However, it acts like there are no holes because it will always fill the next element out.
Insertion:
private int front = 0;
private int back = 0;
public void insertAtFront(int element)
{
(front+1));
dataArray[2*(front + 1) + 1] = element;
front++;
}
public void insertAtBack(int element)
{
dataArray[2*(back+1)] = element;
back++;
}
For removal, just decrement the front or the back. Then when accessing the array, only allow the values between front and back to be shown.
First, does this meet the requirements of a vector? Second, when removing, I am having some major issues figuring out how to get past that special centre point. Say you want to remove the entire array from the front, when you added everything from the back.
Thank you for any assistance.
The secret is to use two arrays. The end of the first array is the "front". The end of the second array is the "back".
I don't understand what you're trying to do with even and odd indices. But having a start index and an end index is basically the way to go - leave space empty at the front so that you can add elements there, and increment the start index again if you remove an element.
Another option is to use a circular array to allow you to add/remove both at the front and at the end efficiently.
There are other variations that could be applied: can you also find an implementation such that inserting/removing at the start, the end and (exactly) in the middle is efficient and has O(1) time?

Moving x,y position of all array objects every frame in actionscript 3?

I have my code setup so that I have a movieclip in my library with a class called "block" being duplicated multiple times and added into an array like this:
function makeblock(e:Event){
newblock=new block;
newblock.x=10;
newblock.y=10;
addChild(newblock);
myarray[counter] = newblock; //adds a newblock object into array
counter += 1;
}
Then I have a loop with a currently primitive way of handling my problem:
stage.addEventListener(Event.ENTER_FRAME, gameloop);
function gameloop(evt:Event):void {
if (moveright==true){
myarray[0].x += 5;
myarray[1].x += 5;
myarray[2].x += 5
-(and so on)-
My question is how can I change x,y values every frame for new objects duplicated into the array, along with the previous ones that were added. Of course with a more elegant way than writing it out myself... array[0].x += 5, array[1], array[2], array[3] etc.
Ideally I would like this to go up to 500 or more array objects for one array so obviously I don't want to be writing it out individually haha, I also need it to be consistent with performance so using a for loop or something to loop through the whole array and move each x += 5 wouldn't work would it? Anyway, if anyone has any ideas that'd be great!
If you have to move 100 objects, you have to move them. No alternatives.
But what you can really do to save performance, is optimize the solution itself. A few cents from me:
Of course the loop has to be applied in your case, managing 100+ assignments line by line is definitely not the right way to go. Although you gain nothing performance wise with just using a loop.
Try grouping the objects. As I see above, you seem to be moving all those objects with similar increment. Group them all into larger movieclips (or Sprites) & move that instead.
Learn Blitting & caching methods to save a lot on performance, Or you would sooner or later hit on the road where your logic cannot be twisted anymore & performance will be a pain.
Also, in extent of the previous step, do consider using Sprite Sheets if you have multiple states of the same object.
Finally, I would also like to caution you to not waste time on micro optimizations & thinking about them.
You can use some container sprite and add the blocks to that on creation:
// Some init place
var blockContainer:Sprite = new Sprite();
addChild(blockContainer);
Make the blocks:
function makeblock(e:Event){
newblock=new block;
newblock.x=10;
newblock.y=10;
// Add the block to the container
blockContainer.addChild(newblock);
myarray[counter] = newblock; //adds a newblock object into array
counter += 1;
}
And the gameloop:
stage.addEventListener(Event.ENTER_FRAME, gameloop);
function gameloop(evt:Event):void {
if (moveright==true){
blockContainer.x += 5;
}
// etc...
}
This way you'll only have to move one object. Of course this method will only work so long as all the blocks need to move in the same direction. By the way, a for loop will work just as well - 500 iterations is nothing. The only performance issue will likely be just rendering and that will happen regardless of what method you choose, as you have to somehow move the blocks (in other words, performance here is not really the issue as you have to render the movement change, the only question is how you choose to implement the movement for your own coding convenience).

Winform treeview sorted property is slow

I have a winforms TreeView control with the Sorted property set to true. I also override the default sorter by assigning and instance of IComparer to the TreeViewNodeSorter property.
Unfortunately adding a few thousand nodes using the AddRange function takes perhaps 10 seconds. If I set Sorted to false the AddRange function is < 1/2 second. (please no discussions about the validity of adding so many nodes)
Aha I hear you say.. there is a problem in my IComparer object. Not according to the profiler. Barely any time is spent in the sorting object and yet the AddRange function is right at the top of the list of slow functions.
The problem is easy to replicate in a test project. Simply create a list of TreeNodes and add it to the an existing expanded tree node using the AddRange function. This will use the default sort on the tree text - again it is disproportionately slow.
To demonstrate how disproportionately slow it is if I disable the Sorted property in the test probject and use the List<T>.Sort function (with a delegate that compares the Text of the nodes) on my list of nodes before adding them to the tree there is virtually no delay.
This leads to the workaround of sorting the nodes manually before using AddRange. That's OK but it means a lot of work to find the correct insertion point when adding nodes to an existing set of child nodes - rather less convenient than simply setting Sorted to true.
Is there anyway to speed up the behaviour?
EDIT - it seems the only way is to sort before adding.. it's a bit of a hassle but I came up with the following extension method:
public static void AddSortedRange(this TreeNodeCollection existingNodes, IList<TreeNode> nodes, TreeView treeView, IComparer sorter)
{
TreeNode[] array = new TreeNode[nodes.Count + existingNodes.Count];
existingNodes.CopyTo(array, 0);
nodes.CopyTo(array, existingNodes.Count);
Array.Sort(array, sorter);
treeView.BeginUpdate();
existingNodes.Clear();
existingNodes.AddRange(array);
treeView.EndUpdate();
}
It is quicker to copy the existing nodes to an array, append the new nodes, sort the array and then replace that trying to manipulate nodes inline in the tree view - the slowest operation in the above code is the existingNodes.Clear() call
The performance problems you have are related to the fact that you are adding items to a sorted TreeView. What happens behind the scenes when you add to a sorted list is that for each item that you are adding, it tries to find it's place, which means that it needs to go through the whole list for each item, now imagine how many iteration that makes for each new item :)
What you can do is this:
TreeView tv = new TreeView(); // Just so I have a TreeView variable
TreeNode[] nodes = ... // Well, your list of nodes that you want to add
tv.SuspendLayout();
tv.Sorted = false;
tv.Nodes.Clear();
tv.Nodes.AddRange( nodes );
tv.Sorted = true;
tv.ResumeLayout();
For performance reasons we are using the SuspendLayout/ResumeLayout methods to disable the painting process used by the TreeView when manipulating it's items, which we would cause by removing the items and then adding them as well, since it would need to repaint to add the new item that you are adding (for each of the items).
Right before we are doing any changes to the Nodes Collection we have to call Sorted = false; to disable the sorting (this is just temporary - the user will not see any changes because of SuspendLayout).
Then just add the items to the collection (since the TreeView is not sorted for the time being it should be really quick).
Then we enable the sorting again by calling Sorted = true; setting the Sorted Property to true will cause for the collection to do a sort.
This way, the sort will be performed only once (and therefore the TreeView will just go once through the items).
One more thing, if you have a custom sorter defined for the ListView (tv.ListViewItemSorter), set it to null before adding the items as well, just temporary of course, re-enable it again before the ResumeLayout call.
I experienced a locking situation using the Sort() method.
It worked fine for weeks, then once, it stucks, stucking my application with 25% CPU in the task manager.
var allTags = _TagEngine.GetTags(1, force);
try
{
TagTree.BeginUpdate();
TagTree.Nodes.Clear();
foreach (var rec in allTags)
{
... adding nodes in the tree
}
TagTree.Sort(); // <= stuck here !
}
finally
{
TagTree.EndUpdate();
}
So I watch inside the Sort() method using a decompiler, and I noticed it handles already the BeginUpdate/EndUpdate feature internally.
Then I moved the TagTree.Sort() outside the BeginUpdate/EndUpdate, and it works fine since.
var allTags = _TagEngine.GetTags(1, force);
try
{
TagTree.BeginUpdate();
TagTree.Nodes.Clear();
foreach (var rec in allTags)
{
... adding nodes in the tree
}
}
finally
{
TagTree.EndUpdate();
}
TagTree.Sort();
I hardly understood what happened here. Why it worked in the past, and suddenly stoped. Frankly, I did not had time enough to dig further and anyway, the most important is here : it works again.
I made a simple extension to the TreeView control. It is very fast. It moves internal storage to a Dictionary which makes a huge difference. In my real world example I have 100000 records that I need to load. It took 37 minutes before, but now it takes 2.2 seconds!!
You can find example and code on CodeProject: http://www.codeproject.com/Articles/679563/Fast-TreeView

Handling ObservableCollection CollectionChanged Event

I've seen code like the following in the Silverlight toolkit and can't understand how it is safe to do:
private void ItemsSourceCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
// Update the cache
if (e.Action == NotifyCollectionChangedAction.Remove && e.OldItems != null)
{
for (int index = 0; index < e.OldItems.Count; index++)
{
_items.RemoveAt(e.OldStartingIndex);
}
}
}
If you remove an item from say index 5 doesn't that change the current index of every item in the _items collection after index 5 to be one less than before? So then how is it safe to continually remove items using their "old" indexes like this code does?
I'd really like to understand why this works.
Any ideas?
This code looks like it is removing a contiguous set of items from a particular starting index. If you read the remove call carefully:
_items.RemoveAt( e.OldStartingIndex );
you will notice that it is iteratively removing items from a constant index. This means it is collapsing the list by removing items in a contiguous range. This may very well be correct - assuming that is the intent of the code.
The loop executes as many times as e.OldItems.Count indicates. So (presumably) it is told how many items to remove starting from a given index.
As a general practice, you have to be careful about how you remove items from collections for a couple reasons:
Item indexes do indeed change as you remove items. So care must be taken to avoid errors resulting from item index positions shifting.
Mutating a list while iterating over it (as in a foreach loop or with an explicit IEnumerator) results in exceptions. You cannot mutate a list (either add or delete) while iterating - it invalidates the iterator.

Resources