I'm making a bomberman game in a C# windows form application. It has over 300 pictureboxes (walls) that are placed on a panel. The picturebox of bomberman himself is also on that panel.
When the location of bombermans picturebox changes, all the controls on the panel are automatically refreshed. Because there are so many controls on that panel, and because the location of the picturebox changes multiple times per second, the program becomes laggy when I try to move.
I want to have control over the refresh event of the panel (and it's controls), because I think my problem is solved when only the pictureboxes that need to be refreshed, are refreshed programmatically.
I hope someone can help me out with this!
Ruud.
If you move the child, the parent has to be refreshed because it may need to draw the area where child was located previously. It would also mean that all children (of parent) would get refreshed.
OTH, using so many controls may not be a good idea. I would suggest you to keep data structures describing walls and then use it to draw it within Panel (or your custom control). You can write your own logic for hit testing (mouse or keyboard click within wall boundary) by capturing mouse/keyboard events at Panel/Parent level. With correct organization data structure, hit testing can be very efficient.
You are trying to paint the whole form which will surely take time . If you want to change only a part of the form, which in your case is Moving the bomberman to a new position, Only invalidate the area you want to repaint and then pass it to the Invalidate method.
Do something similar to this.
//Invalidate previous position of bomberman
Rectangle invalid = new Rectangle(picturebox1.Location.x,picturebox1.Location.y,picturebox1.Width,picturebox1.Height);
Invalidate(invalid);
//Add code to move your picture box and then call above two lines again
invalid = new Rectangle(picturebox1.Location.x,picturebox1.Location.y,picturebox1.Width,picturebox1.Height);
Invalidate(invalid);
Note sure but somthing similar polished code would work...
Here is a link to an example for reference. http://msdn.microsoft.com/en-us/library/ms229628.aspx
Related
I'm a little bit frustrated with forms and feel like there have to be some features that I do not know yet (I'm still new to this). Currently I want to toggle two panels on button click, and have one panel move out on the left while the other moves in on the right. I can get it working somehow, but I'm losing so much time because I can only work on the panel that I see and have to keep dragging the panel that is out of the main form into the main form in order to see it and work on it.
Is there a way to also draw elements that are technically out of the draw range?
The panels should have transparent background and the main form background should not move , so moving in another form does not look like a viable option.
I am have been trying all day to figure out how to not allow controls that I draw on event to check and see if there is another control there and if so to move it over so they do not overlap. I need them to be able to be overlapping if the user drags them there but on the creation of the control to check and move them if necessary. I am trying to create a card game and dont want controls to be hidden behind controls (cards) that the user has not yet moved manually. I am using picture boxes as my cards. Any help would greatly be appreciated. Here is a screen shot of my form. The darker panels are whats in the players hand. The panels that are a light grey are the playing field. Ideally, the user would play a card and it would try and place it in the top left of the panel. if there is a card that intersects then move it over until it doesn't touch a card. Basically find a open space to put the card.
Have you tried using the flow layout panel Class it's under the toolbox=> container with this control you can set how controls are added to it.
I have created a class that allows the user to drag panels on a forms. How can I ensure
that the user does not place two panels on top of each other? If they do, I would like to shift/or highlight one of the control while they are both overlapped.
I tried setting this in OnMouseDown event but that didn't quite work.
Also, the number of panels on the form vary depending on the number of pictures the form needs to show. Each panel has a picturebox inside the panel.
A much better approach is to use the Rectangle.Bounds.IntersectsWith method, which does the check for you and can produce cleaner code. I'm personally unaware of any performance issues or benefits, one way or the other, although I would venture a guess that simply looping over your controls and checking them with this would be faster than building lists and loops both.
Picturebox pic = new Picturebox();
foreach(Control picturebox in Form1){
if (pic.Bounds.IntersectsWith(picturebox.Bounds))
{
//We have a problem, Houston, because we just collided!
}
}
I hope this helps, even though you asked this question some time ago.
So I was able to solve this question with the help of sgud's suggestion.
The trick was to use Rectangle.Intersect method inside OnMouseUp event raised.
Here is the intuition I used behind it. (it might not be the neatest solution)
1) Create a list of all the controls inside my main panel.
2) Traverse through the controls and create a list of all the Rectangle Bounds for each control. you can get this by control.Bounds
3) Go through the list of Bounds and intersect it with the currently active element's bound.
If the returned rectangle has height and width the same as the active control then assign change the back color property.
I hope this helps to anyone else that have a similar problem
I'm trying to write a simple GUI that renders a number of images using the Graphics' object primitives. What I want to have is a series of areas that I can paint to in isolation of the other areas, so that each painting "canvas" has it's own origin within the global coordinate frame of the top-level form.
So far I have tried adding several panels to a FlowLayoutPanel. However, they seem to be getting placed one on top of the other, as only one onPaint method is being called. I can override the Form's onPaint to invalidate the other panels, which are then painted, but not displayed.
Besides setting the sizes, and initialising the FlowLayoutPanel, is there something I'm missing? Is there a better way of doing this?
Code: http://pastebin.com/30Uf9AGF
based on the names of your classes, it looks like you are designing a game ... maybe you want to take a look at Microsofts XNA framework?
however, the problem with the code you provided is, your layoutPanel is not sized correctly, therefore its child-controls are not visible on the main form... since painting is only done for visible items ... there is no painting for most of your FloorDrawPanels ...
try changing the size of your layoutPanel or setting its dock mode to fill
You don't set the size of the FlowLayoutPanel. It will default to 200 x 100 with a Margin of 3. You fill it with controls that are 100 x 100. Given the margin, only one of those controls can ever be visible at the same time. It is therefore no surprise that you only ever get one paint event, Windows only asks visible controls to paint themselves.
Not quite sure what was intended, start by making the FLP bigger. And set its AutoScroll property to true so that the user can scroll the other controls into view. Using the designer would have been a quick way to find this out btw.
I just wasted my entire evening on something which I thought would be very simple but it seems WPF and Google are letting me down completely.
I need a grid, 6x6 of which I fill every row and column with a custom control. I want to be able to navigate through this grid via the keyboard (I can get those events, no problem) but I cannot seem to find how I can always have the selected grid row/column in the center of my window.
I found some carousel alike implementations, but most of them only work in a single direction and I want two way navigation, yet none seem to support this nor can I extend them to do this.
I essentially want to create a PSP alike grid navigation.
One easy way is to do this:
Create a scrollable form.
Add a 6x6 grid of child controls.
In the GotFocus (or similar) event for all the controls, set the parent form scroll offset to an appropriate position to centre the child.
This is pretty straight-forward thing to implement, with a little bit of maths to work out how to centre the x,y position of a control by setting the scroll offsets (it can be tricky/confusing, but as long as you understand the coordinate systems used for scrolling, not too bad)
Or, another approach that avoids scrolling via the windows APIs and using custom controls:
Create a form
Override OnPaint to draw your grid of 6x6 "controls" as simple graphical shapes or bitmap images centred on the selected "control".
Handle keyboard (KeyDown/Up) and mouse handling (MouseDown/Up) events to make the 36 areas of the graphic respond to user inputs in the way you desire. You'll have to track the selected item and force the window to redraw its graphics to show the new state. Enable double buffering to stop it flickering.
The first approach gives you a lot of windows-based handling for free (tabbing between controls, remembering where the input focus is, and directing events to separate classes for each "control", for example). The second approach strips away all this "help" but gives you complete control over everything, which can often help avoid unintended behaviours (e.g. it won't move the input focus when the user presses Tab unless you specifically write the code to make it do that).