Jump to content


Photo

[Solved] Draw continual line without holes, how?


  • Please log in to reply
16 replies to this topic

#1 Thaudal

Thaudal

    GMC Member

  • GMC Member
  • 237 posts
  • Version:GM:Studio

Posted 01 June 2012 - 05:18 PM

I'm making a game where the player needs to draw specific shapes with the finger. Sometimes they can be drawn in one go, sometimes the player needs to release the finger one or more times.

Right now I'm placing a big sprited dot at the finger in each step it's held in, then draw it to a surface and remove it. This works fine for most parts, but if the player moves his/her finger really fast, the line will have holes in it.

I tried putting the room_speed up from 30 to 300, which helped tremendously. This leads me to believe that the player is moving his/her finger fast than the room's framerate, hence because the dot is created every step, it will be holed.

But naturally, setting the room_speed up to such a ridicilous number isn't optimal in any way. So how would I go about doing this?

Edited by Elminster, 08 June 2012 - 02:17 PM.

  • 0

#2 sneekyllama

sneekyllama

    GMC Member

  • GMC Member
  • 784 posts

Posted 01 June 2012 - 05:29 PM

You need to interpolate. The simplest way to do this is to draw a line from 1 point to the other. You can try and write equations to interpolate the points in between each time you sample input to attempt to be more precise than just drawing a straight line but a straight line is the simplest. If you want it to look better you would try to interpolate an arc by using direction based on the points before and after the dot you are checking.

Basically it is unrealistic to try and get a high enough sample rate from the user to have a perfectly smooth line, you need to fill in the data using math to predict as closely as possible to where the user might have been. It will never be perfect but that is fine. Usually with good interpolation it will be so close that it doesn't matter.

[Definition] Interpolate: 4. Mathematics To estimate a value of (a function or series) between two known values.

Edited by sneekyllama, 01 June 2012 - 05:33 PM.

  • 0

#3 Thaudal

Thaudal

    GMC Member

  • GMC Member
  • 237 posts
  • Version:GM:Studio

Posted 02 June 2012 - 02:30 PM

Even though I follow your theory, could you give an example of how this could be done? Even some pseduocode would be much appreciated. Basically anything that could get me moving along. I'm kinda stuck here.
  • 0

#4 Lune

Lune

    hic quoque transibit

  • GMC Member
  • 513 posts
  • Version:GM:Studio

Posted 02 June 2012 - 03:11 PM

Straight line:
//creation
old_mouse_x = mouse_x;
old_mouse_y = mouse_y;

//draw
draw_line_width(old_mouse_x, old_mouse_y, mouse_x, mouse_y, 10);
old_mouse_x = mouse_x;
old_mouse_y = mouse_y;

Edited by Lune, 02 June 2012 - 03:13 PM.

  • 1

#5 Thaudal

Thaudal

    GMC Member

  • GMC Member
  • 237 posts
  • Version:GM:Studio

Posted 02 June 2012 - 04:57 PM

I can't use a straight line for anything. It needs to be completely dynamic and usable for random shapes (like letters and stuff).
  • 0

#6 cotycrg

cotycrg

    GMC Member

  • GMC Member
  • 851 posts
  • Version:GM:Studio

Posted 02 June 2012 - 05:36 PM

You need to use surfaces, bro. On said surface, draw lines from point a to point b. I'm actually doing that in a project I'm working on right now!
  • 1

#7 Crhonos

Crhonos

    GMC Member

  • GMC Member
  • 219 posts
  • Version:GM:Studio

Posted 02 June 2012 - 06:46 PM

Make the line go from the last place the finger touch to the new place, this will fill the holes.


something like this: ----*"----"*-----
Result ------------------
The center part was a hole, that was filled by the line going from the last spot * to the new spot *.
  • 0

#8 Thaudal

Thaudal

    GMC Member

  • GMC Member
  • 237 posts
  • Version:GM:Studio

Posted 02 June 2012 - 07:46 PM

Using Lune's code with surfaces as suggested by cotycrg works great. Only one problem: I need the line to start anew if I've released the mousebutton at any point. Right now, if I release and start drawing again, the points will be "connected" once again due to the way this is coded.

I don't know if this would work - but could I somehow store each "clickpoint" in an array that is increased constantly, so that each "oldmousex", "oldmousey", "mousex" and "mousey" is stored in its own index? This way, I should be able to put new coordinates into the draw_line() function all the time. Would that idea work in practice?
  • 0

#9 cotycrg

cotycrg

    GMC Member

  • GMC Member
  • 851 posts
  • Version:GM:Studio

Posted 02 June 2012 - 08:16 PM

You're putting way much thought into that.

Just do this..

if(mouse_check_button(blahblahblah)){
 
mouse_check+=1;

 if(mouse_check>1){ 
  /*draw stuff*/ 
  }

}else{mouse_check=0;}

This will make it so that it doesn't connect the points. The result is that you maybe off by one frame, but I mean it's worth it.

Edited by cotycrg, 02 June 2012 - 08:18 PM.

  • 0

#10 Thaudal

Thaudal

    GMC Member

  • GMC Member
  • 237 posts
  • Version:GM:Studio

Posted 02 June 2012 - 10:36 PM

You're putting way much thought into that.

Just do this..

if(mouse_check_button(blahblahblah)){
 
mouse_check+=1;

 if(mouse_check>1){ 
  /*draw stuff*/ 
  }

}else{mouse_check=0;}

This will make it so that it doesn't connect the points. The result is that you maybe off by one frame, but I mean it's worth it.


Maybe I interpreted your code incorrectly, but as far as I logically read it and as far as testing it in practice goes, it does the exact same thing.

Here's my step event code. The surface is drawn in the draw event.

if(mouse_check_button(mb_left))
{ 
 mouse_check+=1;
 if(mouse_check>1)
 { 
  surface_set_target(surf)
  draw_line_width(mouseOldX,mouseOldY,mouse_x,mouse_y, 10);
  mouseOldX = mouse_x;
  mouseOldY = mouse_y;
  surface_reset_target()
 }
}
else
{
 mouse_check=0;
}

Wasn't this what you meant?
  • 0

#11 Crhonos

Crhonos

    GMC Member

  • GMC Member
  • 219 posts
  • Version:GM:Studio

Posted 02 June 2012 - 11:46 PM

I think he suggested that in the else of "mouse_check>1" you should put something like "now this line if finished, the next time he taps it will be another line"

edit: Lol, wait in the else put
mouseOldX = mouse_x;
mouseOldY = mouse_y;

Edited by Crhonos, 02 June 2012 - 11:55 PM.

  • 1

#12 Thaudal

Thaudal

    GMC Member

  • GMC Member
  • 237 posts
  • Version:GM:Studio

Posted 03 June 2012 - 01:27 AM

I think he suggested that in the else of "mouse_check>1" you should put something like "now this line if finished, the next time he taps it will be another line"

edit: Lol, wait in the else put
mouseOldX = mouse_x;
mouseOldY = mouse_y;


Of course, how could I have overlooked that! That made all the difference! The nature of draw_line() makes small ugly holes when drawing smooth rounds, but that is easily fixed by placing round sprite substitues as well to supplement the lines. So, using that technique along with Lune, cotycrg and Chronos' help, this now works. Thank you guys so much - this has been a tremendous help! :)
  • 0

#13 cotycrg

cotycrg

    GMC Member

  • GMC Member
  • 851 posts
  • Version:GM:Studio

Posted 03 June 2012 - 03:28 AM

No problem! Glad we could be of help!
  • 0

#14 Thaudal

Thaudal

    GMC Member

  • GMC Member
  • 237 posts
  • Version:GM:Studio

Posted 04 June 2012 - 09:18 PM

It seems my problems are not entirely over. Today I tested this on iOS. The solution that worked on Windows emulation (the one above) doesn't work completely on iOS; somehow, it doesn't reset the mouseOldX/mouseOldY upon release.

I've tried using device_mouse_check() and device_mouse_x/y as well as device_mouse_raw_x/y instead of mouse_button_check() and mouse_x/y. If I use those instead, the drawing dot seems to appear in the upper left corner instead no matter if I'm holding the finger down or not. If I use the exact version as above on iOS, it does the same old problem where the lines are "connected". What could cause this? It has to be something along the lines that iOS interprets mouse coordinates and press states differently from Windows. But... How, and how can I use that to fix this?
  • 0

#15 Crhonos

Crhonos

    GMC Member

  • GMC Member
  • 219 posts
  • Version:GM:Studio

Posted 04 June 2012 - 10:00 PM

I can't offer much help as i don't have IOS module, but:
Try to use instead of
if(mouse_check_button(mb_left)){

}else{

}

This:
if(mouse_check_button(mb_left)){

}

if (mouse_check_button_released(mb_left)){

}


Edited by Crhonos, 04 June 2012 - 10:00 PM.

  • 0

#16 GM Studios

GM Studios

    GMC Member

  • GMC Member
  • 188 posts
  • Version:GM:Studio

Posted 04 June 2012 - 10:49 PM

Use the device functions instead e.g. device_mouse_x(0), device_mouse_y(0) and device_mouse_check_button(0,mb_left).

Edited by GM Studios, 04 June 2012 - 10:49 PM.

  • 0

#17 Thaudal

Thaudal

    GMC Member

  • GMC Member
  • 237 posts
  • Version:GM:Studio

Posted 08 June 2012 - 02:16 PM

Turned out it was a problem elsewhere in my code. Now completely fixed. Thanks again to all who helped. :)
  • 0




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users