Of targets, interface, and rotations...
BlitzPlus Forums/BlitzPlus Programming/Of targets, interface, and rotations...
| ||
I am planning a tower defense game -- except the "towers" are pretty detailed and are likely to be harder to turn (if they turn). Note that I haven't begun coding this particular program at all, but I have just discovered how to use ATan2, Sin, and Cos to aim a shot at something (which I credit to Saxon Physics and the lesson on vectors). Unfortunately, I don't understand some of the other things I think will be important to make the game work... Question #3: In an interface that allows the user to click on an object to activate it (show its range and give it upgrades and all that), how do you go about making sure that one and only one is active? I think that's all for now... but I expect I'll find more later, once I actually get around to getting all of the sprites done and then actually starting to code the thing. Oh well. Anyway, if you know the answer to any of those, I would be very grateful if you could tell me. Thank you! |
| ||
Q1 - First Last Before After are used with collections of types. I'll explain here: (Can't guarantee syntax correct, not at a machine with blitz at present) Type MyObject Field X End Type For i=1 to 10 MyInstance.MyObject = New MyObject MyInstance\X = i Next FirstInstance.MyObject = First MyObject LastInstance.MyObject = Last MyObject SecondInstance.MyObject = After FirstInstance NinthInstance.MyObject = Before LastInstance graphics 800,600,0,2 text 0,0,firstinstance\x text 0,15,lastinstance\x text 0,30,secondinstance\x text 0,45,ninthinstance\x flip waitkey delete each MyObject end Regarding using 'last' to target furthest - a bit unnecessary, I don't know your game's logic but the last instance of an 'enemy' is not necessarily the furthest away. Simply do a distance check through each of your enemies and pick the one with the highest value. Question 2: As many rotations as you want - just don't use the rotateimage command and expect it to perform well at real time. Pre render or prerotate your images as many times as you want, and then simply draw them. The PC doesn't care what your image looks like in blitzplus - it is just a collection of pixels after all - so will draw it just as fast if the little man is facing left as if he is facing right ---> as long as you have already stored the images in memory. DO NOT USE ROTATEIMAGE and expect realtime results.... Question 3: Use a variable, and store whether that object is currently active. For example: Type IconObject Field Name$ Field AmIActive eND tYpe Icon.IconObject=new IconObject Icon\Name = "Switch 1" Icon\AmIActive = 0 Icon.IconObject=new IconObject Icon\Name = "Switch 2" Icon\AmIActive = 0 ;then somewhere later in your code you would do this:(pseudocode) "CurrentIcon.IconObject is that of Switch 1" "if mouseclick on Switch 1 then DoNotAllowPress=0 For OtherIcons.IconObject=each IconObject If OtherIcons\AmIActive=1 and Handle(OtherIcons)<>Handle(CurrentIcon) then DoNotAllowPress=1:Exit next If DoNotAllowPress=0 then do your standard action here for the new icon endif endif |
| ||
#1 - Yeh, the last/first refer to where the object is stacked in memory... is it the "last one in the pile", or the "first one in the pile". It doesn't refer to 'closest' enemy. For finding the closest enemy you could have something like this: function getClosestEnemy.enemy(yourtower.tower) closest.enemy = null for e.enemy = each enemy if (closest.enemy = null) closest.enemy = e.enemy elseif (distance(yourtower, e.enemy) < (distance(yourtower, closest.enemy) closest.enemy = e.enemy endif next return closest.enemy end function Please notice that I used a non-existent "distance" function, but if you use 3d stuff, then of course you can use "entityDistance". If you use 2d stuff, then replace 'distance' with something that works. |
| ||
#1 - Yeh, the last/first refer to where the object is stacked in memory... is it the "last one in the pile", or the "first one in the pile". It doesn't refer to 'closest' enemy. Yes, but if you create the enemies in order of their coordinates and they're following a set path, I believe First would target the one at one end. Still, I've just realized that using First or Last could make the tower fire at something out of range, so figuring out the closest either to the tower or the end of the path (where they go out and make you lose lives) is definitely a better way. Regarding the rotations -- I think I'll just use 16. They won't be any bigger than 32 x 32 anyway. But there's one thing I'm not getting now about these examples. closest.enemy = e.enemy You can change the instance name of objects? I had no idea... But how does this work with multiple towers that probably aren't aiming at the same thing? And Matty, I'm afraid I have no idea how your example for clicking on one of the units is supposed to work. I got lost somewhere around here: "CurrentIcon.IconObject is that of Switch 1" "if mouseclick on Switch 1 then DoNotAllowPress=0 For OtherIcons.IconObject=each IconObject If OtherIcons\AmIActive=1 and Handle(OtherIcons)<>Handle(CurrentIcon) then DoNotAllowPress=1:Exit next If DoNotAllowPress=0 then do your standard action here for the new icon endif endif Specifically, DoNotAllowPress and all the things you did with that confused me, and it almost sounds like once you've clicked on one, you can't click on any of the others... I guess it might help if I name the game whose interface inspired me. What I want is to be able to click on any of the units and have a status thing come up on the sidebar, maybe with an upgrade or two, and then to be able to click on either another one or the ground and have the view change accordingly. The Bloons Tower Defense games, by Ninja Kiwi (requires Flash, I'm not sure what version, but 8 and up work for sure), is the game that brought about my approval of tower defense, and I want this interface to be something like that. Anyway, I've decided about the rotations, and I see that First and Last don't really suit me. Thank you for your help so far! |
| ||
Yes, but if you create the enemies in order of their coordinates and they're following a set path, I believe First would target the one at one end. yes, if the path is straight... but if your path isn't a "line", then you gotta have distance thing. You can change the instance name of objects? I had no idea... please notice that "closest.enemy" is merely a pointer to a certain enemy. In the beginning it's null, but then you make it to point to a specific object. I could have: thing.enemy = e.enemy anotherthing.enemy = thing.enemy whatnot.enemy = e.enemy and they would all point to the same object. But how does this work with multiple towers that probably aren't aiming at the same thing? Well, why couldn't they be aiming at the same thing? I think it would be allowed for different towers to aim & shoot the same thing: consider having 7 towers and only one enemy approaching: it would be pretty stupid if only one tower would aim & shoot them. If you want to make sure they aren't aiming the same thing, then you'd need additional field defined in "type enemy", which would say that "somebody is aiming me". something like here: type enemy field turretThatIsPointingMe.turret ... other fields end type then in the loop, you'd add a thing where you define which turret is aiming the enemy Juts a quick code, so you could probably figure out better ways to handle things - but this should give you an idea. |
| ||
Suggestion on doing the selection: - create a gui element, where you define "clicked object" type gui field selectedUnit.unit end type when you click units, then you would simply have something like: function setSelectedUnit(gui.gui, unit.unit) gui\selectedUnit = unit end function In the sidebar you'd have: function showUnitInfoInSidebar(gui) show(gui\selectedUnit\health) show(gui\selectedUnit\armor) show(gui\selectedUnit\whanot) end function What comes to 'selecting unit', I'm not totally sure, but I'd guess you would: - need to figure out 'which unit was clicked' - set the gui item to point to that selected object - and then make sure sidebarinfo simply shows the selected object info |
| ||
Well, why couldn't they be aiming at the same thing? I agree; they should be able to aim at the same thing, but only if it's in range and would normally be targeted by both of them. I guess I was really asking how to manage more than one "closest target," as it would be possible to have every tower on the field choose a different target. With a For... Each... Next loop for the "closest targets"? And about the selection thing... I'm totally mixed up right now. Maybe I'd better wait on that one until I start coding. ... But please do post if you think of something. I just may not have a lot of time to try to implement them for a little while. |
| ||
I was helping a friend make a similar game in bmax and we just used a variable called sellectedtower. Each tower had its own number and since you couldn't have more that like... 200 of each tower, we checked to see which type of tower was selected by seeing if its number was inbetween 0-200 or 201-300 or 301-400... you get the point |
| ||
So... when one clicked on a tower, selectedtower was adjusted to match the tower's number? Sorry about all the questions jumbled together, but I haven't used the mouse much, and neither did Maneesh... Thank you! |
| ||
woa... too many questions for me to read right now. sorry I don't have time. Im sure this code will answer your questions... or create new ones :) here is the code... I translated it to bb2d earlier so it should work in b+ sorry not heavily commented... hope it helps :D Edit you just click on the red or blue circles to select them to place towers of that color somewhere. you can also click on previously made towers to change whether they are active of inactive the major purpose of this code is to show how to access a tower's properties efficiently and effectivly... well my way isn't the most effiecient but it is simple and effective :) |
| ||
That's okay. I don't have too much time for coding, either. Thank you! |
| ||
ok I will have to wait till tommorrow to do that... sry don't have time :) |
| ||
Like I said, that's okay. Thanks! [EDIT] Oh, but I did have another question for the 'room' at large: Question #4: How do you get an image with 16 different rotations to display the closest direction to an in-between angle? I wouldn't think that the only way to do it would be to use a super-long string of If statements asking if "player\angle >= 0 And player\angle < 22.5" and such. If someone knows of another way, could you tell me, please? Thank you! (This one might be done, but as I won't be able to tell until I've grasped the solution to another question, I won't confirm that yet.) |
| ||
ok I just copied and pasted the comments from my other program... now I really have to go so I can't post any more tonight. Here it is commented a little more. |
| ||
did this help or is it still confusing? As for your other question... get the angle of the target. lets call that angle x. Now multiply by 16 and divide by 360 and put that part in an INT ( (x*16)/360) statement like that and blitz should round to the nearest whole number. Assuming you have an array with the rotations in it this would be the number you put into the array |
| ||
Ok for three, this is my suggestion: I would store the x/y coordinates in an array, as well as a Boolean for activated or not. Then, on every mouse click, 'clear' the third column of the array that contains the 'active' variable (by setting them all to false), then, if the cursor is on the tower (in relation to x and y variables) change that variable to true. So during your interface/update function, just scan the list for the variable that is true, then use the corresponding tower in your function. I hope that made sense. |
| ||
Sauer... I never thought of that :D that would have made my old game so much simpler. Sauer's suggestion is simpler and easier to understand but it depends on the way you want the user to place the towers. If you want them to be able to place them at any x and y then I think my method is the only practical way. If you want the towers to snap to a grid then I agree with sauer that arrays are the way to go. |
| ||
Yeah I think both are feasible and even a creative combination of each could work as well. Now its up to you Mr. Khan. |
| ||
I think the tower-ID method will work nicely enough for me. I haven't really used arrays much, although I have used them to get exact rotations. As for the Int((player\angle * 16) / 360) thing, though... As ATan2# can output negative angles, it seems like it could call for a negative frame/array-position. Would I have to add 180 to the resulting angle to get all positives, or should I plug in Abs(player\angle) for the equation and then have an extra If statement to help it decide which frame to use or something? In other news, I've started coding! (So far, I've made it to the part where you choose the difficulty level, which at this point means Easy, and replaced the mouse. Any time now, I might actually start on the main loop.) |
| ||
no you have to add 16 if the output from the int statement is negative... I would suggest not worrying about that until you get to it. |
| ||
Okay, now that I'm farther along now, I'll go through my other posts and strike out the things I'm fairly sure I understand now. *goes and does that* And so I find that my main question now is about determining the closest enemy to each tower: But how does this work with multiple towers that probably aren't aiming at the same thing? ... I guess I was really asking how to manage more than one "closest target," as it would be possible to have every tower on the field choose a different target. With a For... Each... Next loop for the "closest targets"? In other news, I can place towers! And they cost money! |
| ||
If that is all you are having trouble with then you are coming along well. Just loop through all of the towers and all of the enemies and use the distance formula. Have a dummy type that you use and have a variable to determine what the closest distance so far. |
| ||
To find the closest enemy, use the distance formula. So, when you're scrolling through your tower types, scroll through enemies inside that loop, and check their distances with the formula ((x1-x2)^2+(y1-y2)^2)^.5, compare the results, and then set your sights on the one with the smallest result from that formula. |
| ||
Ohhhhhhhhh! *lightbulb* You mean something like you check every enemy for distance within the tower loop and so you change it for every tower... and as the weapons aren't homing it doesn't matter which enemies are closest after that! Okay, I'll see if I can get that going. ... Only I didn't know you could use carats to make BlitzPlus recognize exponents. You can? ... Well, it seems you can, so now I'll try it. Thank you! |
| ||
Okay, now I've discovered another question. It has nothing whatsoever to do with interface or rotations, but it at least has a very little to do with targets... Question 5 (or, as the other four were answered clearly enough, B1): Is it possible to determine whether an image collides with a line drawn with the Line command? And if so, how? It would be very, very helpful, as then I could attempt a line-based effect and actually have it do something. Oh, and I have a pretty involved background, which I believe could make ImageRectCollide less useful. Thank you! |
| ||
Draw the line onto an image, then do an image to image collide? As long as your image has a backround colour, the same as the mask, it will only check for the pixels of the line. |