This site requires JavaScript, please enable it in your browser!
Greenfoot back
SanderDub
SanderDub wrote ...

2013/12/11

Make an actor follow a line

1
2
SanderDub SanderDub

2013/12/11

#
So I'm trying to make a game similar to Flight Control where a user draws a line to guide an Actor along a path. Here's the scenario : Ship Control Right now I'm using a different line object actor that creates a new instace on mouse click (left for a blue line, red for a red line, the appropriately colored ship will rotate and move towards the closest guide object). When you drag your mouse, it creates a line of objects and if the first node is within range of the right boat, it will start moving along the line, constantly removing a line object and orienting on the next. I have a few things that are bothering me and I can't quite figure out though; - How to make the line of objects solid when I move the mouse too quickly. Maybe I should be using a different method than a seperate actor that guides the boats, but this was the only option that came to mind. Any suggestions on making the objects spawn more rapidly or how to connect them so they form a solid line would be awesome. - How to align the ship so that it doesn't stay slightly diagonal when following a straight horizontal line after taking a turn up/downwards. The movement isn't really natural at the moment, since ships generally don't drift Need for Speed-style through ports. Any other general suggestions that would improve this project would be nice. Keep in mind that I'm a beginning programmer and this is all self-taught. Don't be too harsh ^^.
danpost danpost

2013/12/11

#
The title of this discussion should be more like 'Making a line for an actor to follow'. With the method you are using now, you are getting large gaps when the mouse is moved quickly. If you create an actor at every pixel between those currently being created, you will end up with quite a few actors, and this may cause some lag. If you add three instance 'int' fields to the class your mouse 'drag' detection is at (one to hold the drawing mouse button and the other two to hold the coordinates the mouse was last at), you can then set all three fields when a mouse button is pressed; for each mouse drag event and for the final mouse clicked event, you can create a line actor to 'connect' the last location to the current one and save the current one. These lines can be created horizontal (from left to right) with the appropriate length, placed halfway between the last and current location of the mouse and turned the appropriate angle using 'Math.atan2'. The lines should also hold the color value given them. Your ships can then find the appropriate line by the color they hold, take on their rotation, follow them from back to front and change to the next line. This process would probably require more fields in the Ship class (one for the line it is currently on and one for its offset from the center of that line). A continuous check to see if more than one line is intersected should be made to jump from one line to the next. The width of the image of the line object can be more than one to avoid skipping over it (the line drawn on the image can still be of width one)
SanderDub SanderDub

2013/12/11

#
Sound advice, and a good idea indeed. One question that I really can't seem to grasp though is this : How do you make a line actor with a variable line length? Is there some sort of draw function inside greenfoot?
danpost danpost

2013/12/11

#
You can use 'Math.hypot' to get the length between the two locations. You could add one or two to the length to ensure that the consecutive lines cross.
SanderDub SanderDub

2013/12/13

#
Updated my scenario. And Dan, I appreciate your input but I'd rather keep the flowing lines as I have them right now. I would like to know one more thing before I'm starting to get statisfied. Right now when I use multiple boats of one color, they will attempt to follow the same path crashing into eachother as a result. Is there a way to put each created line of actors into a list / array, and make the ships that the lines were made for only follow this array/list of guide-actors? So if I dragged a line from yellow boat 1, it would make an array of line actors called lines1. Then boat 1 would only follow the lines1 array of waypoints. Is it possible to realise this?
danpost danpost

2013/12/13

#
I am sure there are several ways to accomplish that, since you are using actors. Using an array or separate classes would both work, but neither is really necessary. You could have your line actors and the boat that follow them both hold a key number where the boat will only follow lines with the same number that it has. In other words, add an instance 'int' field to the Boat class and to the Line class. Give each boat a different value for that field. When creating the line objects for the boats, have the value of that field in the line take on the same value as the boat that is to follow it. Then have the boats only follow lines that have the same value in its field. Something to think about: instead of 'int' values, you could just have a unique Color value for each boat and that would determine the color of the line and the color to follow. The line does not have to hold the Color value in a field, but it could to make it more accessible, rather than getting the image and getting the color from it.
SanderDub SanderDub

2013/12/13

#
How do I add a seperate value for each line though? Giving the boats one I understand; just add an int to the Actor itself. But seeing there are multiple instances of each color line actor to be created during the game and present alongside eachother, how do I make one yellow boat follow one line and the next yellow boat ignore that line and take another one instead? I really appreciate your help - and on such short notice too. You're a great asset to this community dan :)
danpost danpost

2013/12/13

#
if (Greenfoot.mouseDragged(this))
{
    // create your line object and assign the value of 'this' boat to it
}
The value can be given to the line object at the time of construction by adding a parameter to the constructor or by calling a method to set the value after construction.
Super_Hippo Super_Hippo

2013/12/13

#
While reading, I knew that the word 'this' will pop up. I even wanted to suggest it. This way you can make every line only available for the ship which created it. Making the points into lines is a great idea which should be tried. Two other things: 1. Delete all the lines (points at the moments) of the actor if you click the actor again. This way you can create another line and delete lines which can be in the wrong place. 2. You can increase the Greenfoot speed to get more points for more accurate lines. Just let the ships act() method only execute every 10th frame or something like this.
SanderDub SanderDub

2013/12/13

#
Could you write a piece of code that adds an int to the object you create when the mouse is dragged? Im currently already using mouseDragged() to detect what type of line to draw. I just really don't know how to add a parameter that holds an int when creating a new object... Help me out with an example of the constructor? Thanks guys, appreciate the help!
danpost danpost

2013/12/13

#
It would be similar to the way you set the int (or color) value of the ships.
SanderDub SanderDub

2013/12/14

#
I don't set the color value of the ships, they're 3 seperate actors that randomly spawn at the left side of the screen. I have no clue as a beginning programmer how to give the boats individual variables. Would it be something like this (psuedo code)
CREATE int shipline = 0;
IF mousedragged ON yellowboat
THEN CREATE yellowpath AND ASSIGN shipline;
shipline++;
danpost danpost

2013/12/14

#
Could you update your Ship Control scenario? this time check the 'Publish source code' checkbox so I can see what you may understand at this point.
SanderDub SanderDub

2013/12/14

#
Crash detection hotfixed :) works perfectly now, probably not the most efficient way but it works so I'm happy.
danpost danpost

2013/12/14

#
There are a couple of things you should be aware of: (1) asking 'if (this != null)' is like asking 'if (true)' (2) in your 'placeGround' methods, you are getting 2 instances of MouseInfo objects; both instances should be equivalent, so you can use the first one throughout the method (3) using separate classes for the same object of different colors is taking subclassing to an extreme; but, to understand this, you probably should read up on how state (color, or an ID value, is, or can be considered, a state of the object) is used in object-oriented programming. Please refer to the Java tutorials; specific the trail: Learning the Java language.
There are more replies on the next page.
1
2