I was wondering if it is possible to create multiple of the same object that is written in a separate file.
I have two files: main.lua and player.lua.
This is player.lua:
local player = { }
function player:create (x, y, sp)
self.img = love.graphics.newImage ('images/player.png')
self.x = x
self.y = y
self.speed = sp
end
return player
I want to include this file in main.lua. I know I can't use require "player" because require only allows a file to be loaded once but it doesn't need me to specify a file path. I tried using dofile() which actually did exactly what I wanted it to do, however, it does requires me to specify a full file path which I don't want to do.
So this is the part from main.lua:
local Player = require "player"
local Player2 = require "player"
-- local Player = dofile("/long/path/to/game/player.lua")
If I can't use require, is there a way to get the current file directory and use it like this:
local Player = dofile(filepath .. "player.lua")
You should approach this by changing create to a function which actually creates new instances of Player, instead of modifying the singleton object.
-- Player.lua
local Player = {}
function Player:create (x, y, sp)
self.__index = self
return setmetatable({
img = love.graphics.newImage('images/player.png'),
x = x,
y = y,
speed = sp
}, self)
end
return Player
Now you can use Player:create to create multiple instances.
-- main.lua
local Player = require 'Player'
local player1 = Player:create(10, 10, 5)
local player2 = Player:create(40, 40, 2)
Consider reading chapter 16 of Programming in Lua, which covers Object-Oriented Programming.
that loads the image serveral times... couldnt you just load an image once then call that image in a varable later like so:
-- Player.lua
local Player = {}
local img1 = love.graphics.newImage('images/player.png') <-- loaded one time
function Player:create (x, y, sp)
self.__index = self
return setmetatable({
img = img1,
x = x,
y = y,
speed = sp
}, self)
end
return Player
Related
I tried to make an item spawn every 60 seconds and in one of two locations, but when I tried to use vector3 it didn't spawn in the location of the "spawnplace1" or "spawnplace2", but it spawned ontop of the roka being copied and didn't move. Also I don't think I can hold the copied roka's either. Here's the code!
local roka = workspace["Rokakaka Fruit"]
local itemspawns = workspace.ItemSpawnLocals
local itemspawn1 = itemspawns["Item Spawn 1"]
local itemspawn2 = itemspawns["Item Spawn 2"]
local place1 = itemspawn1.Position
local place2 = itemspawn2.Position
wait(60)
local spawnplace1 = math.random(1,2)
local spawnplace2 = math.random(1,2)
if spawnplace1 == 1 then
roka2 = roka:Clone()
roka2.Parent = workspace
local roka2handle = roka2.Handle
roka2handle.Position = Vector3.new(itemspawn1)
elseif spawnplace1 == 2 then
roka2 = roka:Clone()
roka2.Parent = workspace
local roka2handle = roka2.Handle
roka2handle.Position = Vector3.new(itemspawn2)
end
print(spawnplace1)
print(spawnplace2)
The Vector3 holds coordinates of a point in 3D space. You have only provided 1 of 3 pieces of information in the constructor. To construct a Vector3, you need to provide the Y and Z axes as well, like this :
roka2handle.Position = Vector3.new(1, 2, 3)
But you don't need to explicitly create a Vector3 to get your code working. You can just assign the positions of the spawn locations to your newly created fruit, and that should do the trick. This way, you can add lots more spawn locations, and you don't need to update the script each time.
-- grab some things from the workspace
local roka = workspace["Rokakaka Fruit"]
local itemSpawns = workspace.ItemSpawnLocals
-- choose a random spawn location
local spawnLocations = itemSpawns:GetChildren()
local spawnNumber = math.random(1, #spawnLocations)
local spawnPosition = spawnLocations[spawnNumber].Position
-- spawn and move a new fruit to one of the spawn locations
roka2 = roka:Clone()
roka2.Parent = workspace
local roka2handle = roka2.Handle
roka2handle.Position = spawnPosition
-- debug
print("spawning fruit at : ", spawnPosition)
As a side note, if roka2 is a Model, you may want to consider using roka2:SetPrimaryPartCFrame( CFrame.new(spawnPosition)) to move it around.
I am making a game, and in it the player needs to spawn some bullets:
game
├──player = {}
└──bullets = {}
I've heard in godot you can use parent to address the parent node and wonder if i can imitate that somehow.
I currently have 2 potential solutions:
local game = {
player = player.new(x, y, spawnBullet),
bullets = {}
}
spawnBullet being a function. Although that would require doing that for all functions, which might be annoying.
My second solution would be to pass game iteslf to the player
local game
game = {
player = player.new(x, y, game),
bullets = {},
And in player.new(x, y, parent)
player.parent = parent
Are these solutions all there is available or are there better ones?
Whatever, I made a node module myself.
local node = {}
node.__index = node
local new = function(name, parent)
assert(name, "Please provide a name for the node")
local newNode = {
name = name,
parent = parent,
}
return setmetatable(newNode, node)
end
return setmetatable(
{
new = new,
__call = new,
},
node
)
are you using an engine/framework?
I am using gideros and I do it this way, example:
main game
-- myplayer
-- bullets
In my player class:
-- SHOOT
if self.isspace then
local bullet = Character_Bullet.new(self.world, ...)
self:getParent():addChild(bullet)
self.isspace = false
end
My project structure is following:
--Shooter
----sprites
------background.png
------player.png
------zombie.png
----units
------player.lua
------zombie.lua
----main.lua
----load.lua
----update.lua
----draw.lua
And my main.lua will have the following:
local Bullet = require("units.bullet")
local Player = require("units.player")
local Zombie = require("units.zombie")
require("load")
require("update")
require("draw")
require("functions")
love.window.setTitle("Shooter")
function love.load()
Load()
end
function love.update(dt)
Update(dt)
end
function love.draw()
Draw()
end
For example, bullet.lua:
local Bullet = {}
bulletSprite = love.graphics.newImage('sprites/bullet.png')
function Bullet.create()
local newBullet = {
pos = {},
speed = 10,
sprite = bulletSprite,
direction = 0,
dead = false
}
return setmetatable(newBullet, {__index = Bullet})
end
function Bullet:setPos(x, y)
self.pos.x = x
self.pos.y = y
end
function Bullet:setDirection(angle)
self.direction = angle
end
function Bullet:move(dt)
local distance = self.speed * dt * 60
self.pos.x = self.pos.x + math.cos(self.direction) * distance
self.pos.y = self.pos.y + math.sin(self.direction) * distance
end
function spawnBullet(bullets, player)
local newBullet = Bullet.create()
newBullet:setPos(player.pos.x, player.pos.y)
newBullet.direction = player.angle
table.insert(bullets, newBullet)
end
The problem is that none of the files in units folder will load properly. From the error log I can see that it tries to search for bullet.lua in the root directory and then various love2d and lua libraries.
I have tried various things like require("./units/bullet") or replace / with . but so far, no luck.
Extracting those files from the units folder into root folder will work. Loading images from sprites folder works, however (for example love.graphics.draw(sprites.background, 0, 0)).
Any help?
I found out the problem was that while my main.lua had correct requires, my update file didn't.
Two things come to mind.
Make Sure LUA_PATH is set to your project directory
add return Bullet, return Player and so on... into each module you have created
I am trying to construct a method that automatically adds and renames objects in Lua. I have the add method for adding the object, but I am not sure how to make it so that it renames each object. I'm thinking of adding an if statement, but I don't know how to construct it in a way that it will rename the object each type it loops.
Here is what I have so far:
frogBody = {density = .8, friction = 0.3, bounce = 0.1, radius = 10} -- body Type
local onPlayerSpawnObject = function(object) -- method to spawn object
local layer = map:getTileLayer("Enemies")
local frog = movieclip.newAnim{ "FrogMini.png", "frogMiniRed.png" } -- object that spawns
frog.x = object.x ; frog.y = object.y
frog.myName = "frog"
frog.isHit = false
physics.addBody(frog, frogBody)
end
Thank you for all of your help!
I think that what you mean is that you would like to access the frogs objects from your example distinctively ?
If that is the case you could either assign the return of the add function to a lua table, or directly assign to the table inside your function.
local frogs = {}
frogBody = {density = .8, friction = 0.3, bounce = 0.1, radius = 10} -- body Type
local onPlayerSpawnObject = function(object) -- method to spawn object
local layer = map:getTileLayer("Enemies")
local frog = movieclip.newAnim{ "FrogMini.png", "frogMiniRed.png" } -- object that spawns
frog.x = object.x ; frog.y = object.y
frog.myName = "frog"
frog.isHit = false
physics.addBody(frog, frogBody)
table.insert(frogs, frog)
end
-- To print a distinct frog from the collection, replace 1 by your index
print (frogs[1].myName)
The main creates a simple 2d array. Now i want to create a addeventlistener for each object in the table. I presume i do this in the class? Although i have created a taps function and then defined addeventlistener but i ma getting errors.
--main.lua--
grid={}
for i =1,5 do
grid[i]= {}
for j =1,5 do
grid[i][j]=diceClass.new( ((i+2)/10),((j+2)/10))
end
end
--dice class--
local dice = {}
local dice_mt = { __index = dice } -- metatable
function dice.new( posx, posy) -- constructor
local a=math.random(1,6)
local b= true
local newdice = display.newText(a, display.contentWidth*posx,
display.contentHeight*posy, nil, 60)
--newdice:addEventListener("tap", taps(event))
return setmetatable( newdice, dice_mt )
end
function dice:taps(event)
self.b = false
print("works")
end
function dice:addEventListener("tap", taps(event))
This stumped me till today. The main problem is that you're making newdice a Corona display.newText object and then reassigning it to be a dice object. All the Corona objects act like ordinary tables, but they're actually special objects. So you have two options:
A. Don't use classes and OOP. As your code is now, there's no reason to have dice be a class. This is the option I'd go with unless you have some compelling reason to make dice a class. Here's how you would implement this option
--dice not a class--
local dice = {}
local function taps(event)
event.target.b = false
print("works")
end
function dice.new( posx, posy) -- constructor
local a=math.random(1,6)
--local b= true
local newdice = {}
newdice = display.newText(a, display.contentWidth*posx,
display.contentHeight*posy, nil, 60)
newdice:addEventListener("tap", taps)
newdice.b = true
return newdice
end
or B. Use a "has a" relationship instead of an "is a" relationship for the display object. Since you can't make them both a dice object and a display object, your dice object could contain a display object. Here's how that would look.
--dice class--
local dice = {}
local dice_mt = { __index = dice } -- metatable
local function taps(event)
event.target.b = false
print("works")
end
function dice.new( posx, posy) -- constructor
local a=math.random(1,6)
--local b= true
local newdice = {}
newdice.image = display.newText(a, display.contentWidth*posx,
display.contentHeight*posy, nil, 60)
newdice.image:addEventListener("tap", taps)
newdice.b = true
return setmetatable( newdice, dice_mt )
end
There were some other problems as well. In your taps function event handler you have to use event.target.b instead of self.b. Also, in dice.new b is a local variable so it's not a member of your dice class.
Remove the last line.
The addEventListener function should be called like this
newdice:addEventListener("tap", taps)