I was making a script that creates a particle inside the player but i got the error "Unable to assign property Speed. NumberRange expected, got number "
Here is the code:
local LeftArmParticle = Instance.new('ParticleEmitter', player.Character["Left Arm"])
LeftArmParticle.Texture = "rbxassetid://"..armAu
LeftArmParticle.Speed = 1
LeftArmParticle.Lifetime = 1
LeftArmParticle.Rate = 50
Seems pretty self-explanatory. You need LeftArmParticle.Speed = NumberRange.new(1), as the NumberRange type represents upper and lower bounds. Since you want it to be a constant speed of 1, you do not need to specify both bounds. You will have to do the same with the Lifetime property.
Related
I'm currently trying to spawn aliens for a space invaders game I'm creating in class. I'm using a while loop with a counter to adjust an array to a given variable value. This way I can increase the number of aliens without any re-writing. The problem is, although my aliens spawn, the x position is not increasing as I would like it to. I only see one Alien on the screen so I've concluded that they are all spawning, but only with a 1-pixel difference, therefore unnoticeable. Here's what I have so far, any help would be greatly appreciated!
//Add and display given amount of aliens...
while (alienAmount > displayLoopCounter) {
aliens.append(SKSpriteNode(texture: SKTexture(imageNamed: "ClassicAlien")))
self.addChild(aliens[displayLoopCounter])
//Location
aliens[displayLoopCounter].position.y = CGFloat(-15)
aliens[displayLoopCounter].position.x = CGFloat(displayLoopCounter + 25)
print(aliens[displayLoopCounter].position.x)
displayLoopCounter += 1
print(displayLoopCounter)
//Have we run out of aliens yet?
if displayLoopCounter > alienAmount {
displayAliens = false
}
You just need to change the spacing you're setting between aliens. In other terms, you need to set the x position of each alien sprite to have more spacing between them. Currently, you are just adding displayLoopCounter to the x position of each alien. Since displayLoopCounter only increases one at a time, the aliens are all spawned with a 1-pixel difference to each other. If we want a bigger difference, we will need to multiply displayLoopCounter by our intended spacing so that we get that spacing between each alien.
You can just set a spacingBetweenAliens variable with a numeric type (such as Int or CGFLoat or Double) and change this line:
aliens[displayLoopCounter].position.x = CGFloat(displayLoopCounter + 25)
To this:
let basePosition = displayLoopCounter * spacingBetweenAliens
aliens[displayLoopCounter].position.x = CGFloat(basePosition + 25)
This way, the aliens will be spawned with the value of spacingBetweenAliens in pixels between them.
Using Tiled I generated a Lua file which contains a table. So I figured that I'd write a for loop which cycles through the table gets the tile id and checks if collision is true and add collision if it was. But, I've been unable to get the tile id's or check they're properties. But it returned a error saying that I tried to index nil value tileData.
Here is the Map file
return {
version = "1.1",
luaversion = "5.1",
-- more misc. data
tilesets = {
{
name = "Tileset1",
firstgid = 1,
tilewidth = 16,
tileheight = 16,
tiles = {
{
id = 0,
properties = {
["Collision"] = false
}
},
}
}
layers = {
{
type = "tilelayer",
name = "Tile Layer 1"
data = {
-- array of tile id's
}
}
}
}
And here is the for loop I wrote to cycle through the table
require("Protyping")
local map = love.filesystem.load("Protyping.lua")()
local tileset1 = map.tilesets
local tileData = tileset1.tiles
local colision_layer = map.layers[1].data
for y=1,16 do
for x=1,16 do
if tileData[colision_layer[x*y]].properties["Colision"] == true then
world:add("collider "..x*y,x*map.tilewidth, y*tileheight,tilewidth,tileheight)
end
end
end
Try this:
tileset1 = map.tilesets[1]
instead of
tileset1 = map.tilesets
lhf's answer (map.tilesets[1] instead of map.tilesets) fixes the error you were getting, but there are at least two other things you'll need to fix for your code to work.
The first is consistent spelling: you have a Collision property in your map data and a Colision check in your code.
The second thing you'll need to fix is the way that the individual tiles are being referenced. Tiled's layer data is made of 2-dimensional tile data laid out in a 1-dimensional array from left-to-right, starting at the top, so the index numbers look like this:
You would think you could just do x * y to get the index, but if you look closely, you'll see that this doesn't work. Instead, you have to do x + (y - 1) * width.
Or if you use zero-based x and y, it looks like this:
Personally, I prefer 0-based x and y (but as I get more comfortable with Lua, that may change, as Lua has 1-based arrays). If you do go with 0-based x and y, then the formula is x + 1 + y * width.
I happen to have just written a tutorial this morning that goes over the Tiled format and has some helper functions that do exactly this (using the 0-based formula). You may find it helpful: https://github.com/prust/sti-pg-example.
The tutorial uses Simple Tiled Implementation, which is a very nice library for working with Tiled lua files. Since you're trying to do collision, I should mention that STI has a plugins for both the bump collision library and the box2d (physics) collision library.
I know scene coordinates are (0,0) at center so how can i distribute 4 SKNodes along the width using a for loop
for index 1...4 {
let node = SKNode()
node.postion = evenly distribute along the scene width. who can i do it?
}
You could use the width of the scene divided by the number of nodes minus 1. This would then be multiplied by the index minus 1, then added to the minimum x value of your scene.
let widthRange = scene.frame.maxX - scene.frame.minX
for index 1...4 {
let node = SKNode()
node.postion = scene.frame.minX + widthRange/(4-1) * (index-1)
}
This should place each node an equal distance away from each other along the width of the scene, starting from each edge.
If your index for the for loop doesn't start at 1, the code would need to be modified to something like this:
let widthRange = scene.frame.maxX - scene.frame.minX
var counter = 0
for index 352...356 {
let node = SKNode()
node.postion = scene.frame.minX + widthRange/(4-1) * counter
counter+=1
}
If you're unsure of which version to use, use the second version, as it's less reliant on the format of the for loop (as long as you reset counter to 0 before every time you use this).
If you need any clarifications as to what does what, feel free to ask.
Edit
This should clarify what the code actually does.
let widthRange = scene.frame.maxX - scene.frame.minX is used to get the size of the scene, then set it to a variable that is used later. Making this a variable is sort of optional as you could just use the scene size, however I put it this way so it's less messy.
var counter = 0 simply makes a counter variable, that's used in the for-loop, to place the nodes. Make sure to set it to 0 before every time you run the loop. counter+=1 is then used later so each node is multiplied by an increasing value, which creates the different x-positions. (I'll get into that later)
node.postion = scene.frame.minX + widthRange/(4-1) * counter is the complicated line. First, I use scene.frame.minX to start placement from the lowest width/x-position. widthRange/(4-1) is a little harder to understand. It uses the scenes width (from earlier), then divides by one less than the amount of nodes. The best way to understand this, is that to cut a rectangle (only in a single direction) so it has 2 cuts through it (2 of the nodes), and 2 edges (the other 2 nodes), you would need 3 sections. (The rectangle would be cut into 3). This gets the distance between each node. The pattern of #ofNodes-1 follows for every amount of nodes. The * counter part is the part that makes the node's x-position actually change. Since every time the loop is gone through, counter increases by 1 (starting at 0) the amount of "sections" from before (widthRange/(4-1)) is increased by 1.
I am quite new to programing in swift and I am working on a music app for iOS that adjusts the font size of the text in a UILabel in proportion to the string's length. In my code, I am trying to count the number of characters in the string statement and have it plugged into a formula, but for some reason Xcode gives me the error: Cannot call value of non function type double I tried setting the value to a CGFloat but it still gives me the same error on the "let b = 41.2 - .8(a) line. Thank you so much and sorry if this seems like a basic question.
let title = "Let It Bleed"
AlbumName.text = title
let a = title.characters.count
if ( a <= 19){
let b = 41.2 - .8(a)
let fontsize = CGFloat(b)
AlbumName.font = AlbumName.font.fontWithSize(fontsize)
}
A screenshot of the code with the error
I assume you expect "0.8 times a" with .8(a).
Three things:
You need leading 0 to represent fractional values in Swift.
You need explicit operator * for multiplication.
You need to convert numeric types to match for mathematical operations.
All these included, your line of interest becomes like this:
let b = 41.2 - 0.8 * CGFloat(a)
I'm getting a (a nil value) error when i try to do this :
player = display.newSprite( imageSheet, "sequenceDataPlayer"..math.random(1, 7) )
Looking at a test print :
print ("sequenceDataPlayer"..math.random(1, 7) )
It prints the data oky 'sequenceDataPlayer1'
What Im i doing wrong here ?
Your print statement is just printing the string "sequenceDataPlayer" concatenated with a random number between 1 and 7.
It took me a little while to figure out how to use sprites in Corona, but here's how I do it. I'll use Player for the variables since that's what you're using.
First I create an options variable to get the frames from my Player.lua file:
optionsPlayer =
{
frames = require("player").frames,
}
Then I create a variable for the image sheet:
playerSheet = graphics.newImageSheet( "player.png", optionsPlayer )
After that, I create a variable to set up the name, the sequence of frames, the time it takes to play, and set how many times it will loop:
spriteOptionsPlayer = { name="Player", start=1, count=10, time=500, loopCount = 1}
Finally, I create the new sprite:
spriteInstancePlayer = display.newSprite( playerSheet, spriteOptionsPlayer )
Once I've done all this, I usually set up the x and y positions, xScale and yScale, and other properties along with adding it to a display group.
Last of all, then I play the sprite somewhere:
spriteInstancePlayer:play()
From what it looks like, you want to have 7 different sprites to choose from. Personally, I would just create seven different sprites using all of the steps above and then put them in a table.
sprites = { spriteInstancePlayer, spriteInstancePlayer2, spriteInstancePlayer3, etc.. }
Then when I wanted to play them, I would set the position and visibility and just do:
r = math,random(1, 7)
sprites[r].x = x position
sprites[r].y = y position
sprites[r].isVisible = true
sprites[r]:play()
Of course, then I would want to set listeners to either completely remove the sprite or set the visibility to false when it's done playing, there's a collision(you'd have to add a physics body and set that all up), or whatever else might happen...
There are probably simpler ways to do it, but that's what I do.
Hope this helps.