Programming C, C++, Java, PHP, Ruby, Turing, VB
Computer Science Canada 
Programming C, C++, Java, PHP, Ruby, Turing, VB  

Username:   Password: 
 RegisterRegister   
 using the mouse to draw shapes
Index -> Programming, Turing -> Turing Help
View previous topic Printable versionDownload TopicSubscribe to this topicPrivate MessagesRefresh page View next topic
Author Message
shlitiouse




PostPosted: Sat Apr 16, 2005 9:28 pm   Post subject: using the mouse to draw shapes

Hi, I'm new to this forum, and have been programing with turing for about 6 months now at school. It's come time for our final project of the year, our assignment is to create a paint program. I completed this assigment way ahead of time, and now have 3 weeks to just improve the program. So far I've added a nice little feature where you can type in a width and height value for using the square or circle tools I added. But the problem I'm having here is that typing in the numbers is a little hit or miss if you're actualy trying to draw something, so I was wondering if there would be any way I could have it so that I'd click a location on the screen, then I'd be able to click another location on the screen, and it would draw a line between those two points. I've played around with it for awhile, trying things like
loop
mousewhere(mx,my,b)
if b (button) = 1 then
x:=mx (mouse x)
y:=my (mouse y)
if b=0 then
x1:=mx
y1:=my
end if
drawline (x,y,x1,y1,black)
end if
end loop

I have the basic idea of how it's supposed to work... I just can't figure out how to make it work, can I get any help here?
Sponsor
Sponsor
Sponsor
sponsor
Martin




PostPosted: Sat Apr 16, 2005 10:05 pm   Post subject: (No subject)

Because I'm feeling nice:

code:
var mx, my, b : int
var x, y, x1, y1 : int := 0
loop
    mousewhere (mx, my, b)
    if b = 1 then
        x1 := mx
        y1 := my
        drawline (x, y, x1, y1, black)

    end if
    x := mx
    y := my
end loop
Cervantes




PostPosted: Sat Apr 16, 2005 10:13 pm   Post subject: (No subject)

Hi! Posted Image, might have been reduced in size. Click Image to view fullscreen. Welcome to the forum.
First off, thank you for giving us some detail about your problem. Thank you for showing us some code that you've tried so far. Thank you for giving an appropriate topic name. It seems that I am in your debt. Smile Mind you, it makes things look nicer if you use the [ code] [ /code] tags.

Now to your question. I think you've got the right idea. If the mouse button is pressed, store the coordinates of the mouse at that point. Then, when the mouse button is released, create a second set of coordinates and draw a line (or whatever shape) between the two points.
The flaw of your code is the location of the second if statement (if btn = 0). It will never be true and will therefore never execute the code inside it because if btn = 0 is only evaluated if btn = 1. And if btn = 1, then btn cannot equal 0. Sure, most of the time btn will be 0, but that if statement will never be checked unless btn = 1.
How do we fix this? There are two ways. One is good, one is bad. Let's start with the bad way first, because it's easier to understand.

Turing:

var x1, y1, x2, y2 : int
var mx, my, btn : int
loop
    Mouse.Where (mx, my, btn)
    if btn = 1 then
        x1 := mx
        y1 := my
        loop  %wait until the button is released
            Mouse.Where (mx, my, btn)
            exit when btn = 0
        end loop
        x2 := mx
        y2 := my
        Draw.Line (x1, y1, x2, y2, black)
        exit
    end if
end loop

In this code, we first wait until the mouse button is pressed. Then, we store the mouse coordinates, a lả your initial code. Then, we wait for the button to be released. When it is, we store the coordinates of the mouse in two more variables and draw our line.
This is not so good a method because we enter a loop that will only exit when the mouse button is released. This means that while the user is drawing his/her line, the program cannot be doing anything else that it might need to do, like checking for keystrokes. The program could, however, do this with multiple processes, but that is totally unecessary and silly. So let's ignore I ever mentioned the word 'process'.

I hope you understood that, because we're about to move on to the better, slightly more complicated way. This next method using a flag or boolean variable. It will simply flag whether the button has been clicked previously.

Turing:

var x1, y1, x2, y2 : int
var clicked := false
var mx, my, btn : int
loop
    Mouse.Where (mx, my, btn)
    if btn = 1 and not clicked then
        x1 := mx
        y1 := my
        clicked := true
    end if
    if clicked = true and btn = 0 then
        x2 := mx
        y2 := my
        Draw.Line (x1, y1, x2, y2, black)
        exit
    end if
end loop

So, if the button is clicked and it has not been previously clicked, set the first coordinates and make clicked = true. Next, if clicked = true and the button is not pressed, then that means that the button was just released. Thus, set the second set of coordinates and draw our line, then exit.

Now, let's modify that such that the line is drawn from the original point to the mouse point and multiple lines can be drawn.

Turing:

var x1, y1 : int
var clicked := false
var mx, my, btn : int
loop
    Mouse.Where (mx, my, btn)
    if btn = 1 and not clicked then
        x1 := mx
        y1 := my
        clicked := true
    end if
    if clicked = true then
        if btn = 0 then
            clicked := false
        end if
        Draw.Line (x1, y1, mx, my, black)
    end if
end loop

Same thing, execpt we now have a place to make clicked false. We want it to be false if the button was just released. That way, the button can then be pressed once again. Even if btn doesn't equal 0, we will draw the line, provided the mouse button is down. This way, we see what the line will look like before we actually confirm it. The only thing is we never erase the line. There are a few ways to fix this. First, you could take a picture of the background (using Pic.New) each time through your loop and redraw that. Second, you could have an array of a record that stores x and y coordinates, type of shape, colour, and number (number woudl control the time things are drawn and therefore controls overlapping). This second method, however, would be rather difficult for you, especially if you haven't learned arrays. Wink Another way would be to draw the line when the button is pressed, and then to erase it by drawint a white line over top of it. Then, the line is drawn in it's new position (if the mouse moved).
Turing:

var x1, y1, x2, y2 : int
var clicked := false
var mx, my, btn : int
loop
    Mouse.Where (mx, my, btn)
    if btn = 1 and not clicked then
        x1 := mx
        y1 := my
        clicked := true
    end if
    if clicked = true then
        Draw.Line (x1, y1, mx, my, black)
        delay (10)
        if btn = 0 then
            clicked := false
        else
            Draw.Line (x1, y1, mx, my, white)
        end if
    end if
end loop

However, you cans see that this allows the user to erase stuff just by drawing a line. That's clearly not what we're going for!

There are several ways to do that. But since I'm guessing that, for purposes of simplicity, you won't want to draw the line while the mouse is pressed (and rather only draw it when the button is released), I'm going to leave it at that. If you do want to draw the line at all times, maybe you should reconsider! Laughing Just kidding, if you want to, ask away. I'm not entirely sure how to do it well, but I think you might need to then learn (flexible) arrays.

Cervantes

EDIT: Ha, you're being "nice", Martin, because he didn't do the "I need Help" topic title. Aah, same with me. It's amazing how far a little courtesy can get someone.
shlitiouse




PostPosted: Sun Apr 17, 2005 8:54 am   Post subject: (No subject)

woops, sorry, didn't notice the code button there Embarassed

I ran your codes through, and they did work, although I was playing around with it and found another little interesting thing here

code:
var x, y, x1, y1 : int
var mx, my, b : int
var status : int := 0

loop
mousewhere (mx, my, b)

if status = 1 and b = 1 then
x1 := mx
y1 := my
drawline (x, y, x1, y1, black)
status := 0

end if

if status = 0 and b = 1 then
x := mx
y := my
drawdot (x, y, black)
status := 1

end if

end loop


(hope I used to code function correctly there) Anyways, this program came VERY close to doing what I was looking for (I didn't really care whether I had to click and hold the mouse to be setting the line co-ordinates, or if I could just click once, then click again and it would draw a line)

The idea was that the variable labeled "status" would be set to 0, when the status is at 0 and the button has been clicks, then the x and y co-ordinates would be set and status would be changed to 1, and if status =1 and the button has been clicked, then it would set the x1 and y1 co-ordinates and draw the line (x,y,x1,y1,black).

The only problem with this program was that it would keep drawing lines from the last co-ordinates, I tried experimenting with if status=2 type of thing to get it to stop drawing lines and to start over again. No luck with that. Although what you've done there works great, I'll have to check the turing help files for that Pic.New function though Razz
Unfortunately, no, we haven't been taught about arrays yet. Anyways, I'll let you know how the project goes, and might submit the program to your site once it's all finished and running smoothly Very Happy
shlitiouse




PostPosted: Sun Apr 17, 2005 12:06 pm   Post subject: (No subject)

Alright, I don't know what this forum's preffered method for posting a second question about the same thing after a reply, if you preffer I edit the previous post I will do so in the future, but I've almost figured out everything I needed to... I've got it working, for the most part... Here is the coding I'm using at the moment

code:
var x1, y1 : int
var clicked := false
var mx, my, btn : int
var prntscn : int
%draws a random box, for testing purposes
drawfillbox (50, 50, 150, 150, green)
%gets picture of the blank screen with the box
prntscn := Pic.New (0, 0, maxx, maxy)

loop
    Mouse.Where (mx, my, btn)
    if btn = 1 and not clicked then
        x1 := mx
        y1 := my
        clicked := true

    end if

    if clicked = true then
        if btn = 0 then
            clicked := false
        end if
        %prints the original screen with the green box before drawing the line
        Pic.Draw (prntscn, 0, 0, picCopy)
        drawline (x1, y1, mx, my, black)

    end if
end loop


With this, it will draw a green box I was using for testing purposes, takes a picture of the screen, when I click and hold, it will draw a black line, immediately replacing it with the original screen with the square, thus I can see where my line will be, and I don't have thousands of lines or white marks all over the screen. Everything in this works, except when I click again to draw another line, the first line disappears, I tried adding the code to take the picture of the screen outside of the IFs, but this didn't work, and just gave me the error "Illegal picture ID '0'". Any idea how I can have it so that I'll be able to see what the line will look like before actualy drawing it, but being able to click and draw a second line? Keep in mind this also has to be used for a box function, a circle function, a flag function and a leaf function, so keeping the code as short as possible would be preffered, just to save myself a lot of time and to keep the program more organised.
jamonathin




PostPosted: Sun Apr 17, 2005 1:12 pm   Post subject: (No subject)

What you need to do is take another picture when the mouse is being clicked.
code:
if mouse = clicked then
Pic.Free(prntscn) % We need to free the picture before taking another one
prntscn:=Pic.New (0,0,maxx,maxy)
Pic.Draw (prntscn,0,0,picCopy)
end if
shlitiouse




PostPosted: Sun Apr 17, 2005 4:55 pm   Post subject: (No subject)

Great, the program is complete except for one thing... Among the shapes I need to draw, I must also try to draw a flag (Canadian)
I realise that this is basicaly the same conept I used to do all the other shapes, except I can't find a formula to get the bars to the left and right of the mapple leaf to react properly as I move the mouse, and to stay in purportion. I will also have to find the same type of formula for the mapple leaf. Just to make it a little easier for you, here's a sample code of how to draw a Canadian flag in turing

code:

var mx,my,b:int

loop
mousewhere (mx,my,b)
if b=1 then
drawbox (mx-(10*2),my-10,mx+(10*2),my+10,red)
drawfillbox (mx-(10*2),my-10,mx-10,my+10,red)
drawfillbox (mx+(10*2),my-10,mx+10,my+10,10)
drawfillmapleleaf (mx-10,my-10,mx+10,my+10,red)
end if
end loop


Now what I'm trying to do is get it to draw the same thing starting at the point (x1,y1) and having the purportions of everything change in relation to the mx/my co-ordinates. So far I've tried a few more difficult equations, as well as a few more equations that would fit into the K.I.S.S method Wink
jamonathin




PostPosted: Sun Apr 17, 2005 5:50 pm   Post subject: (No subject)

Think of how a Canadian flag is made. It's in thirds, so we distribute the flag into 3 sections. The red bars and the white bar/leaf.
code:

 drawfillbox (x1, y1, x1 + ((mx - x1) div 3), my, red)
    drawfillbox (x1 + ((mx - x1) div 3) * 2, y1, mx, my, red)
    drawfillmapleleaf (x1 + ((mx - x1) div 3), y1, x1 + ((mx - x1) div 3) * 2, my, red)


P.S. I'm glad to see you're going with the KISS method.

P.P.S. you may want to add a:
code:
drawfillbox(x1,y1,mx,my,white)
before any of the other boxes if you're going to be putting it ontop of other things/colors.
Also, if you're bored, this flag can be done in 3 drawfill's, figure it out. Razz
Sponsor
Sponsor
Sponsor
sponsor
Cervantes




PostPosted: Sun Apr 17, 2005 6:19 pm   Post subject: (No subject)

The Canadian flag definately doesn't look like that... You forgot the space between then maple leaf and the red side bars.
But jamonathin is right in his approach. Get the ratio's you need for the flag and you can make it any size you want!
shlitiouse




PostPosted: Sun Apr 17, 2005 6:53 pm   Post subject: (No subject)

Wow, thanks Very Happy Heh, yeah, forgot about the space between the red bars and the leaf (and I accidentaly made one of the bars green somehow... The sad part is I'm Canadian. Anyways, I didn't exactly get the coding to work, but I do see what you're talking about and get the idea of it, so I'll continue to experiment. Other than that though, the program is finished and ready to hand in, and judging by how friendly and helpful you've all been (not once has someone called me a "noob" just because I'm new) it looks like I've found a new site to hang around Very Happy
*fourstar




PostPosted: Sat Apr 23, 2005 8:43 pm   Post subject: (No subject)

lol yeah im new here too and this site is pretty helpfull, and i have recently just had this paint program too it was fun to do with the special features and all Razz Razz Razz
Display posts from previous:   
   Index -> Programming, Turing -> Turing Help
View previous topic Tell A FriendPrintable versionDownload TopicSubscribe to this topicPrivate MessagesRefresh page View next topic

Page 1 of 1  [ 11 Posts ]
Jump to:   


Style:  
Search: