So I'm playing around with a tutorial script, and I have a turret added that follows the player's movement. This turret should be shooting at the player every few seconds. Before I added collisions or timed shots or anything like that, I found out that the bullet shots actually aren't being shown. So I set it to a key press just to test, and nope, not working.
Full Code
Anything you see wrong? NOTE: I don't get an error when I run it, the bullets just don't show up!
love.keyreleased(key) treats the shift key as a separate and independent key so "X" will never happen. Instead use "x" to trigger a shot.
function love.keyreleased(key)
if key == 'x' then
shoot()
end
end
Once that is fixed you will have issues in your collision detection:
player is not being used as an array as line 52 for ii, vv in ipairs(player) do suggests.
There is nothing stopping a bullet from having a negative velocity and hitting a player or a player being hit by more than one bullet and so they may be added to the remEnemy and remShot table multiple times which will mess up deleting later.
The index shifts that happen when you delete an entry (mentioned by Etan Reisner) also exist.
For your use case, marking an object to be removed by adding it to a set seems like the best approach to me:
local remShots = {}
then if there is a collision or the bullet has negative velocity then
remShots[i] = true
and to remove, iterate in reverse to avoid shifted indices.
for i=#enemyShots,1,-1 do
if remShots[i] then
table.remove(enemyShots, i)
end
end
Performance
A table.remove shifts all the elements above the index down to fill the gap. In the code here the loop removes multiple elements so they are shifted more than once, but as long as your tables aren't huge, this removal process is fine.
I'm note sure what you were going for with the first bullet point, but you can also use the remPlayer to avoid checking for collisions with players that have already been marked for removal when you get that worked out:
if not remPlayer[ii] and CheckCollision...
Related
I am a complete novice! Apologies if this appears utterly basic.
I have a distribution which changes over time (cycles) and I want to show this (single series) on a dynamic plot. I have achieved it by recording a macro while I change the yvalues (by 1 row at a time) and then adding in a delay as follows:
Application.Wait (Now + TimeValue("00:00:01"))
However, I don't know how to define the yvalues range such that it will jump to the next row (of y values) and display that.
It could be up to 200 cycles.
I would like to use R3C3 type notation to define the y values and a 'for i < 200.....next i' approach, but I have tried and failed several times.
The specific issue I have is demonstrated here; see the C3:M3 changing up to C7:M7: please see attached image.
Code issue
Any tips? Thanks.
I want to change the colour of a part when a player stands on it but instead of putting the script inside the part can i put the script in the workspace and identify the part from an event, like Humanoid touched or something?
The reason is that i have 100's of parts which need to react to a touch event so i don't want to put the same script in each part.
Pseudo-code might be
Player touch part event fired
Identify part from event and change colour of part
Thanks
As M. Ziegenhorn wrote, you could put the script in the character or in the foot directly. That would be the "easiest" way of achieveing this.
However, you could also connect a function to each part easily.
In the code below, we check through a model in workspace named 'TouchParts' which (assumingly) contains the parts you want to tie the touch-function up to.
function Touched(self, Hit)
if Hit and Hit.Parent and Hit.Parent:FindFirstChildOfClass'Humanoid' then
-- We know it's a character (or NPC) since it contains a Humanoid
-- Do your stuff here
print(Hit.Parent.Name, 'hit the brick', self:GetFullName())
self.BrickColor = BrickColor.new('Bright red')
end
end
for _, object in pairs(workspace.TouchParts:GetChildren()) do
if object:IsA'BasePart' then
object.Touched:connect(function(Hit)
Touched(object, Hit)
end)
end
end
Doing it this way means anything in your character touching the part(s) will fire the Touched-event, so you would have to add in a check to see whether if tie part touching is a leg or not.
The pros of binding the function to each part instead of to the leg is that the function is only called when you actually touch one of the intended parts, instead of ANYTHING you touch. However, with an increased amount of parts you connect it to, there's also an increased amount of events which will be triggered and is stored in memory. Probably not noticeable on the scale you're working with, but worth keeping in mind.
Been a while since I coded something on roblox so please excuse any blunders I make.
local parent = workspace.Model --This is the model that contains all of that parts you are checking.
local deb = 5 --Simple debounce variable, it's the minimum wait time in between event fires, in seconds.
local col = BrickColor.new("White") --The color you want to change them to once touched.
for _,object in next,parent:GetChildren() do --Set up an event for each object
if object:IsA("BasePart") then --Make sure it's some sort of part
spawn(function() --Create a new thread for the event so that it can run separately and not yield our code
while true do --Create infinite loop so event can fire multiple times
local hit = object.Touched:wait() --Waits for the object to be touched and assigns what touched it to the variable hit
local player = game.Players:GetPlayerFromCharacter(hit.Parent) --Either finds the player, or nil
if player then --If it was indeed a player that touched it
object.BrickColor = BrickColor.new(col) --Change color; note this is also where any other code that should run on touch should go.
end
wait(deb) --Wait for debounce
end
end)
end
end
This is probably one of the most, if not the most efficient way of doing this.
When a player stands on a block, the value "FloorMaterial" (which is in Humanoid) will be telling you what material the user is standing on, but if the user isn't standing on anything, this value will be nil.
Another efficient method is to use Rays. You would need to create a ray from your HumanoidRootPart.
Example:
IsOnGround=function()
local b=false;
local range=6;
local char=game:service("Players").LocalPlayer.Character;
local root=char:WaitForChild("HumanoidRootPart",1);
if root then
local ray=Ray.new(root.CFrame.p,((root.CFrame*CFrame.new(0,-range,0)).p).unit*range);
local ignore={char};
local hit,pos=workspace:FindPartOnRayWithIgnoreList(ray,ignore,false,false);
pcall(function()
if hit then
b=true;
end
end)
else
print("root not found");
end
return b;
end
This would cast a ray from the HumanoidRootPart, towards the direction where the ground should be, with a distance of 6 studs.
Sadly, this method isn't very effective with R15 characters as far as I know.
So for our computer science class, we had to write a program that randomly generates cards, i decided to do mine in batch, because im a massive noob XD
I was confident that i could do it as im quite experienced with it. Even though batch isn't by any means a good 'language' if your going to call it that. I was able to fix most of the problems by myself with some hard work. I am however, still having some issues i don't know how to resolve.
My biggest issues i don't know how to fix are...
Text not being displayed properly.
Numbers (i use for the base of the AI and card generation) sometimes not being defined properly in variables.
The point system just refuses to work not matter what i do.
It sometimes randomly just flat out decides to crash on me if i skip a 'TIMEOUT' or a 'PAUSE'.
Some 'IF' statements not being executed properly even though there exactly the same as the other ones.
I'm sorry if this question is too broad, but i really didn't know quite how to summarize it.
Here is a link to my card game: http://pastebin.com/t2S3yWk5
Here is our question:
1) Create a program that will generate two random numbers - one that maps to a suit (hearts,diamonds, clubs or spades) and one that maps to a card (Ace, 2, 3, ..... Jack, Queen, King)
*Mine is slightly different, it generates two different suits based on two random numbers.*
2) Create a program that will generate a random card and then ask the user to go Higher,Lower or Quit. If the player chooses Higher the next card must be of a higher value or theplayer is out. Likewise for Lower.
3)Extending the previous program, the user will select a trump suit at the start of the game. If the card is a trump suit card then the game continues regardless of the card’s value. The program will keep score and will save the score to a highscore file. The user will also be able to display the current highscore file.
I would like to try and do this stuff (listed above) myself. I just need help trying to fix my existing program.
I hope that if your reading this you could give me some advise or provide solutions to some of my problems. Thanks in advance! :3
Good news; nothing is super wrong with your code, it's just a bunch of little things that seem like a lot. Some off-by-one errors and a missing variable that I can only assume got replicated from copying and pasting.
Text not being displayed properly
I assume this is the "Access denied" errors that your code produces instead of the AI's comments. This is due to the fact that > and < are used for output redirection, so the emoticons you are adding are trying to create a file in a place you don't have access to. Either get rid of them (recommended) or use ^ to escape them (^>:)).
Numbers (I use for the base of the AI and card generation) sometimes not being defined properly in variables
%random% %% 5 results in one of the numbers in the set 0, 1, 2, 3, 4. You currently do not have an if statement for what should happen if 0 is randomly selected. Add an if statement or have the code go back to the top of the section if a 0 is selected.
The point system just refuses to work no matter what I do
You're going to kick yourself...
Your set statements are missing the assignment portion. SET /A %p1p% + 2 should be SET /A p1p=%p1p% + 2 and so forth (or set /a p1p+=2 if you think that looks better).
If sometimes randomly just flat out decides to crash on me if I skip a 'TIMEOUT' or 'PAUSE'
I couldn't replicate that, but the code seemed to work fine when I removed those statements.
Some 'IF' statements not being executed properly even though they're exactly the same as the other ones
Your comment indicated lines 119-132, which include the if statements that assign points. See above for why those aren't working.
Some other recommendations for your code
Your variable names should be more descriptive. For example, ctog doesn't tell me anything about what that variable should be; I can look at the code to see what it does, but without any context, that could be doing anything.
You should add the /i flag to the if statements that check which card you put down so that C1 and c1 get treated the same. On a related note, you should add a check for when the player enters something other than C1 or C2. You can even use a choice command like you did earlier.
:pvic is missing an exit command, so you automatically play again if you win. Combined with the fact that you only check if lt is equal to 2, not greater than or equal to 2, there's no way to stop playing if you win. Also on the subject of end game conditions, there's no if statement for if you tie the computer.
cp1 and num1 are effectively the same variable, there's no reason to have both (same with cp2/num2, ap1/num3, and ap2/num4).
You need some kind of goto at the end of :pc1 so that :pc2 doesn't automatically run after :pc1 finishes.
Looked around with numerous search strings but can't find anything quite like this:
I'm writing a custom log parser (ala analog or webalizer except not for webserver) and I want to be able to skip the hard work for the lines that have already been parsed. I have thought about using a history file like webalizer but have no idea how it actually works internally and my C is pretty poor.
I've considered hashing each line and writing the hashes out, then parsing the history file for their presence but I think this will perform poorly.
The only other method I can think of is storing the line number of the last parse and skipping until that number is reached the next time round. What happens when the log is rotated I am not sure.
Any other ideas would be appreciated. I will be writing the parser in ruby but tips in a similar language will help as well.
The solutions I can think of right now are bound to be brittle.
Even if you store the line number and later realize it would be past the length of the current file, what happens if old lines have been trimmed? You would start reading (well) after the last position.
If, on the other hand, you are sure your log files won't be tampered with and they will only be rotated, I only see two ways of doing what you want, and I'm not sure the second is applicable to you.
Anyway, here goes.
First solution
You store the last line you parsed along with a timestamp. At the next run, you consider all the rotated log files sorting them by their last modified date, figure out which one you read last time, and start reading from there.
I didn't think this through, there might be funny corner cases you will need to handle.
Second solution
You create a background script that continuously watches the log file. A quick search on Google turned out this gem, but I'm not sure if that's even an option for you. Even then, you might want to integrate this solution with the previous one just in case your daemon will get interrupted (because that's clearly bound to happen at some point).
As you read the file and parse the lines keep track of the byte count. Save that. On next read, try to seek to that byte offset in the file. If the file is smaller than the byte count, it's a new file so start at the beginning.
I have this really nasty bug in my program, which somehow changes the value of my variable. I have tried setting break points but can't find the line of code that's the culprit.
Is there any way to pause program execution when there's a line of code that's changing the value of a variable in Xcode 4?
One way would be to find the value changing operations or in general any bug using bisection. Ie. you choose two breakpoints that have the problematic operation in between and move one of them to middle and check if the value still changes. If it does repeat in this halt, if not repeat in the other half.