I have a picture box and I tell it to appear on a random location on another specified larger picture box.
here's my code:
Code:
Sub P2_AppleMove()
Dim P2ax As Integer = CInt(Int((P2Foodarea.Width * Rnd()))) ' sets the random area of the food
Dim P2ay As Integer = CInt(Int((P2Foodarea.Height * Rnd())))
P2Apple.Visible = True
P2Apple.Location = New Point(P2ax, P2ay)
End sub
P2foodarea is a large picture box I created. I only want the apple to spawn on P2Foodarea, atm, it spawns on P1Foodarea which is very weird. P1foodarea is a whole other picture box. I even made new variables as you can see P2ax and P2ay, but it still doesn't spawn on P2Foodarea. I have even tried recreating a new picture box for P2foodarea, no luck please help. thank you.
P2Apple.Location = New Point(P2ax, P2ay)
P2ax will be distance from left of FORM not picturebox, so add - picturebox.Left + P2ax and picturebox.Top + P2ay
P2Apple.Location = New Point(P2ax, P2ay)
P2ax will be distance from left of FORM not picturebox, so add - picturebox.Left + P2ax and picturebox.Top + P2ay
i'm not sure i'm with you there :/ Thing is I have P1foodarea and all P1 works fine all fruits spawn on P1foodarea as they should. its just P2foodarea i'm having problems, and its the exact code just with modified variables :/ and another set of P2 fruit.
I created a project to test
I bet P1Foodarea is first picture box on form in top left corner.
Also you need to subtract P2Apple.Width & P2Apple.Height in the random function
Code:
Sub P2_AppleMove()
Dim P2ax As Integer = CInt(Int(((P2Foodarea.Width - P2Apple.Width) * Rnd())))
Dim P2ay As Integer = CInt(Int(((P2Foodarea.Height - P2Apple.Height) * Rnd())))
P2Apple.Visible = True
P2ax = P2ax + P2Foodarea.Left
P2ay = P2ay + P2Foodarea.Top
P2Apple.Location = New Point(P2ax, P2ay)
End Sub
We'll say that p1food is at (10, 10) and p2food is at (40, 10), and they're both 10 pixels wide and 20 pixels tall. (Certainly your picture boxes are bigger but using small numbers is convenient in examples.)
So if we want something to appear in the p2 food area, you need X coordinates 40-50 and y coordinates 10-30. (We'll ignore some extra calculations that would shrink that range until later.) Let's run your code with a few sample random numbers and see what we get. To review, here's a simplified but functionally equivalent version of your code:
Code:
Dim P2ax As Integer = CInt(P2Foodarea.Width * Rnd())
Dim P2ay As Integer = CInt(P2Foodarea.Height * Rnd())
Let's pick 3 random numbers for the experiment: one close to 0, one in the middle, and one close to 1. That way we'll have a good idea of where items will be placed. I pick 0.1, 0.6, and 0.8. Here's a table that shows what you get:
Note that none of these are inside of the p2 food area. Many of them aren't even inside the p1 food area. Your error is you believe these coordinates are relative to the p2 food area picture box. This is not true.
When you specify the Location property of a control, its coordinates are relative to its parent control. In the simple case, you drop controls onto the form. The top-left corner of the form is (0, 0). So when you make a picture box's location (1, 12), it will display one pixel to the right and 12 pixels down from the top-left corner of the form. There is no way to make a control's Location be relative to some other point, short of putting it inside of a Panel or other container control. When a control is inside of a Panel, it's Location is relative to the top-left corner of the Panel. For example, if you have a panel at (10, 10), and inside the panel is a button with Location (10, 10), the button will appear at (20, 20) in the form, since the panel is 10 right and 10 down from the top-left of the form and the button is 10 right and 10 down from the top-left of the panel.
The solution is not to place panels about your form. The solution is to calculate the position properly.
In my example, the p2 food area is a rectangle at (40, 10) with size (10, 20). If I want to make a point that appears within that rectangle, I have to generate random X coordinates between 40 and 50 and random y coordinates between 10 and 20 (note that technically I want 1 less than the maximum.) To get a random number in these ranges, you have to understand a formula:
Code:
value = rnd() * range + min
rnd() must be a number between 0 and 1. range is the difference between the minimum value and the maximum value. min is the minimum value. If you don't trust this formula, check it with some random numbers. Suppose I want a number between 10 and 20. That's a range of 20 - 10 = 10 and a minimum of 10. Let's check it:
Note how the smallest value produced is the minimum, the largest is the maximum, and something in between gets us a value between the minimum and maximum. That's exactly what we want.
So, if I want x coordinates between 40 and 50:
Code:
Dim p2x As Integer = CInt(rnd() * 10 + 40)
Here's y coordinates between 10 and 30:
Code:
Dim p2y As Integer = CInt(rnd * 20 + 10)
That'll produce values with the right coordinates. Two last tweaks: you'll want to use control coordinates and sizes rather than hard-coded values, and you have to account for the size of the objects you're placing. A 10x10 square placed at (47, 28) is going to be mostly outside of my imaginary p2 food area; so you need to subtract the size of the object you're placing:
Code:
Dim xRange As Integer = p2FoodArea.Width
Dim p2x As Integer = CInt(rnd() * xRange + p2FoodArea.Left - p2.Width)
Dim yRange As Integer = p2FoodArea.Height
Dim p2y As Integer = CInt(rnd() * yRange + p2FoodArea.Top - p2.Height)
This is all ignoring that the right and proper way to generate random numbers in VB .NET is the System.Random class. The Next() method returns an integer in a range you specify; you don't have to work with any formulas! This is how I would write the code (It assumes you've properly set up an RNG variable for the Random instance; if you indicate that you tried this and you get some "RNG not declared" error I will not respond because you didn't read the post. You can instead ask for guidance as to how to set up that variable; that indicates you read the post but don't quite understand, which isn't frustrating.)
Code:
Dim p2x As Integer = RNG.Next(p2FoodArea.Left, p2FoodArea.Width - p2.Width)
Dim p2y As Integer = RNG.Next(p2FoodArea.Top, p2FoodArea.Height - p2.Height)
__________________ .NET Resources My FAQ threads | Tutor's Corner | Code Library
I would bet money 2/3 of .NET questions are already answered in one of these three places.
This is all great, but didn't he say randomly appear somewhere? It's not moving.
Should be x = width of the picture y = height of the picture. From 0 to width and from 0 to height. You'll have x and y. Then move your picture to that cordinate. But the picture MUST be inside the other. If it is not contained, it will not appear randomly within the picture box.
I think the lack of sleep, and the working out all the time is knocking me out. I'm trying to focus on what you guys wrote but a little too much out of it. I made something like this already a few weeks ago. I forgot to mention the area by which it can spawn:
0 To PictureBox.Width
0 To PictureBox.Height
But, maybe this is already mentioned... if the picture is at cordinates:
PictureBox.Width, PictureBox.Height
You won't see the picture. It's in the bottom right corner, out of bounds. So we must:
0 To (PictureBox.Width - OtherPictureBox.Width)
0 To (PictureBox.Height - OtherPictureBox.Height)
And If we need to divide out scales per pixel, incase the ratio doesn't match we would do this:
Name.Width / Screen.TwipsPerPixelX
But most importantly is having the picture inside the other. If it isn't, then the code here will not work. This is how I check:
Code:
MsgBox OtherPictureBox.Container.Name
And to set:
Code:
Set OtherPictureBox.Container = PictureBox
Again, VB 6 code, might have to change in this case.
So Random Number For X:
Code:
Dim sngX As Single
X = CSng(CInt((PictureBox.Width - OtherPictureBox.Width) * Rnd))
Ah wait, this isn't right. Ignore that. Rnd = 0 or 1 when rounded. This doesn't work, I'll edit with solution in a second. You can see if we replace Rnd() with 1 or 0 and multiples... you can't get all numbers inside the picturebox. Instead your only hitting 2 numbers. The end or 0.
Pulled out my function:
Code:
Private Function GetRandomNumber(intFrom As Integer, intTo As Integer) As Integer
'Return Function
GetRandomNumber = CInt((Rnd * (intTo - 1)) + intFrom)
End Function
There now we can use this function:
Code:
Dim sngX As Single
X = CSng(GetRandomNumber(0, PictureBox.Width - OtherPictureBox.Width))
Doing random numbers always confuses me... no matter how many times I practice. But I believe this is correct now. Cheers.... this function doesn't work for (0 to 1), but since we are going past that it doesn't really need to be rewritten to check for such numbers.
I swear this is the last edit, I'm awake now. Ok function won't work with 0 To something. Must be 1 To Something, but we can subtract 1 and fix that.
Code:
Private Sub Form_Load()
'Declare
Dim sngX As Single
'Announce
X = CSng(GetRandomNumber(1, (PictureBox.Width - OtherPictureBox.Width) + 1)) - 1
End Sub
Private Function GetRandomNumber(intFrom As Integer, intTo As Integer) As Integer
'Return Function
GetRandomNumber = CInt((Rnd * (intTo - 1)) + intFrom)
End Function
Had to fix my dumb mistakes. I'll try to avoid that next time. (Get sleep stupid!)
If your sticking with pixels and inside a picture box, maybe you should do data type single?
Dim sngX As Single
I know this doesn't fix the glitch, but the way you wrote this:
Code:
Dim P2ax As Integer = CInt(Int((P2Foodarea.Width * Rnd())))
Could be written:
Code:
Dim P2ax As Single = CSng(CInt(P2Foodarea.Width * Rnd))
Just cleaner and it's single inside a picture box. I believe you still have to convert to integer first to round properly.
Also is the P2Apple's container the P2Foodarea? If not, it will spawn somewhere else. Check it's container.
how do you make P2apple its container for P2foodarea ?
btw I don't need to worry about - height and width, because I made the foodareas smaller to cater for this, so i just put a background image behind and looks good. There's always more than one way to do things.
We'll say that p1food is at (10, 10) and p2food is at (40, 10), and they're both 10 pixels wide and 20 pixels tall. (Certainly your picture boxes are bigger but using small numbers is convenient in examples.)
So if we want something to appear in the p2 food area, you need X coordinates 40-50 and y coordinates 10-30. (We'll ignore some extra calculations that would shrink that range until later.) Let's run your code with a few sample random numbers and see what we get. To review, here's a simplified but functionally equivalent version of your code:
Code:
Dim P2ax As Integer = CInt(P2Foodarea.Width * Rnd())
Dim P2ay As Integer = CInt(P2Foodarea.Height * Rnd())
Let's pick 3 random numbers for the experiment: one close to 0, one in the middle, and one close to 1. That way we'll have a good idea of where items will be placed. I pick 0.1, 0.6, and 0.8. Here's a table that shows what you get:
Note that none of these are inside of the p2 food area. Many of them aren't even inside the p1 food area. Your error is you believe these coordinates are relative to the p2 food area picture box. This is not true.
When you specify the Location property of a control, its coordinates are relative to its parent control. In the simple case, you drop controls onto the form. The top-left corner of the form is (0, 0). So when you make a picture box's location (1, 12), it will display one pixel to the right and 12 pixels down from the top-left corner of the form. There is no way to make a control's Location be relative to some other point, short of putting it inside of a Panel or other container control. When a control is inside of a Panel, it's Location is relative to the top-left corner of the Panel. For example, if you have a panel at (10, 10), and inside the panel is a button with Location (10, 10), the button will appear at (20, 20) in the form, since the panel is 10 right and 10 down from the top-left of the form and the button is 10 right and 10 down from the top-left of the panel.
The solution is not to place panels about your form. The solution is to calculate the position properly.
In my example, the p2 food area is a rectangle at (40, 10) with size (10, 20). If I want to make a point that appears within that rectangle, I have to generate random X coordinates between 40 and 50 and random y coordinates between 10 and 20 (note that technically I want 1 less than the maximum.) To get a random number in these ranges, you have to understand a formula:
Code:
value = rnd() * range + min
rnd() must be a number between 0 and 1. range is the difference between the minimum value and the maximum value. min is the minimum value. If you don't trust this formula, check it with some random numbers. Suppose I want a number between 10 and 20. That's a range of 20 - 10 = 10 and a minimum of 10. Let's check it:
Note how the smallest value produced is the minimum, the largest is the maximum, and something in between gets us a value between the minimum and maximum. That's exactly what we want.
So, if I want x coordinates between 40 and 50:
Code:
Dim p2x As Integer = CInt(rnd() * 10 + 40)
Here's y coordinates between 10 and 30:
Code:
Dim p2y As Integer = CInt(rnd * 20 + 10)
That'll produce values with the right coordinates. Two last tweaks: you'll want to use control coordinates and sizes rather than hard-coded values, and you have to account for the size of the objects you're placing. A 10x10 square placed at (47, 28) is going to be mostly outside of my imaginary p2 food area; so you need to subtract the size of the object you're placing:
Code:
Dim xRange As Integer = p2FoodArea.Width
Dim p2x As Integer = CInt(rnd() * xRange + p2FoodArea.Left - p2.Width)
Dim yRange As Integer = p2FoodArea.Height
Dim p2y As Integer = CInt(rnd() * yRange + p2FoodArea.Top - p2.Height)
This is all ignoring that the right and proper way to generate random numbers in VB .NET is the System.Random class. The Next() method returns an integer in a range you specify; you don't have to work with any formulas! This is how I would write the code (It assumes you've properly set up an RNG variable for the Random instance; if you indicate that you tried this and you get some "RNG not declared" error I will not respond because you didn't read the post. You can instead ask for guidance as to how to set up that variable; that indicates you read the post but don't quite understand, which isn't frustrating.)
Code:
Dim p2x As Integer = RNG.Next(p2FoodArea.Left, p2FoodArea.Width - p2.Width)
Dim p2y As Integer = RNG.Next(p2FoodArea.Top, p2FoodArea.Height - p2.Height)
Wow man, You're really a genius thanks man, solved my problem. So really the reason why it work for P1Foodarea is because that was the first picture box on the form I'll take it :/
how do you make P2apple its container for P2foodarea ?
btw I don't need to worry about - height and width, because I made the foodareas smaller to cater for this, so i just put a background image behind and looks good. There's always more than one way to do things.
That's very true. My approach was the picture is inside another. That is the container method. You can simply move the picture inside another by cut and paste. Just cut a picture box and right click another then paste. Now it's inside it.
Or you could use code to do it. You'll notice you really only need this for run-time purposes.
That's very true. My approach was the picture is inside another. That is the container method. You can simply move the picture inside another by cut and paste. Just cut a picture box and right click another then paste. Now it's inside it.
Or you could use code to do it. You'll notice you really only need this for run-time purposes.
I really don't want to offend but this is completely false. PictureBox is not a container control because it doesn't inherit from ContainerControl. It doesn't break convention and define a Controls property sans inheritance to contain children. Thus it can't contain other controls. You're getting "the controls are on top of each other" mixed with "there is a parent/child relationship" and they are two completely different things. You are describing a solution that is identical to the code in the OP.
Perhaps in VB6 picture boxes could have child controls. VB .NET is not VB6, particularly when it comes to how complicated controls behave. Give solutions a try in VB .NET before you post them; I know how long it takes to make a post like #8 and I can't tell you how much time I've wasted by not writing my examples first and finding out at the end I had something wrong (once a month I probably lose an hour or two to this.)
__________________ .NET Resources My FAQ threads | Tutor's Corner | Code Library
I would bet money 2/3 of .NET questions are already answered in one of these three places.
That wouldn't offend me. Your good, I would try VB.net but I don't have it at the moment or the time to get used to it. I'll definitely when I get a chance.
The ASP.NET 2.0 Anthology
101 Essential Tips, Tricks & Hacks - Free 156 Page Preview. Learn the most practical features and best approaches for ASP.NET. subscribe