I am new to lua language .I have downloaded a class.lua file from github. I wrote a code for game developement by making classes in lua with love2d framework.I was making a pong game that needs paddles and ball,but it is giving me error like this:
Error
Ball.lua:2: attempt to call global 'Class' (a boolean value)
Traceback
Ball.lua:2: in main chunk
[C]: in function 'require'
main.lua:6: in main chunk
[C]: in function 'require'
[C]: in function 'xpcall'
[C]: in function 'xpcall'
I have spent so much time on it to solve but nothing happens.
main.lua
code is:
push =require 'push'
Class=require 'class'
require "Ball"
require "Paddle"
WINDOW_WIDTH=1280
WINDOW_HEIGHT=720
VIRTUAL_WIDTH=432
VIRTUAL_HEIGHT=243
--speed at which we will move our paddles; multiplied by dt in update
PADDLE_SPEED=200
function love.load()
love.graphics.setDefaultFilter('nearest','nearest')
--more 'retro-looking' font object we can use for any text
--os.time() give the time from 1 jan 1970
math.randomseed(os.time())
smallFont=love.graphics.newFont('font.ttf',8)
--set love2d active font to the small font object
scoreFont=love.graphics.newFont('font.ttf' , 32)
--larger font for drawing the score on the screen
love.graphics.setFont(smallFont)
--initialize window with virtual resolution
push:setupScreen(VIRTUAL_WIDTH,VIRTUAL_HEIGHT,WINDOW_WIDTH,WINDOW_HEIGHT,{
fullscreen=false,
resizable=false,
vsync=true
})
--Paddle(x,y,width,height)
player1=Paddle(10,30,5,20)
player2=Paddle(VIRTUAL_WIDTH-10,VIRTUAL_HEIGHT-30,5,20)
--place a ball in the middle of the screen
ball=Ball(VIRTUAL_WIDTH/2-2,VIRTUAL_HEIGHT/2-2,4,4)
gameState='start'
end
function love.update(dt)
--player 1 movement
if love.keyboard.isDown('w') then
--add negative paddle speed to current Y scaled by deltaTime
player1.dy=-PADDLE_SPEED
--player1Y= math.max ( 0, player1Y + -PADDLE_SPEED * dt)
elseif love.keyboard.isDown('s') then
--add positive paddle speed to current Y scaled by deltaTime
player1.dy=PADDLE_SPEED
else
player.dy=0
--player1Y = math.min ( VIRTUAL_HEIGHT -20 , player1Y + PADDLE_SPEED * dt)
end
--player 2 movement
if love.keyboard.isDown('up') then
--add negative paddle speed to current Y scaled by deltaTime
player2.dy=-PADDLE_SPEED
--player2Y=math.max( 0, player2Y + -PADDLE_SPEED * dt)
elseif love.keyboard.isDown('down') then
player2.dy=PADDLE_SPEED
else
player2.dy=0
end
if gameState=='play' then
ball:update(dt)
end
player1:update(dt)
player2:update(dt)
end
function love.keypressed(key)
--key can be acessed by sting name
if key=='escape' then
--function love give us to terminate application
love.event.quit()
elseif key == 'enter' or key == 'return' then
if gameState == 'start' then
gameState = 'play'
else
gameState = 'start'
ball:reset()
end
end
end
function love.draw()
--begin rendering at virtual screen
push:apply('start')
--recent versions of pong has grey color it sets grey color
love.graphics.clear( 0 , 0 , 0 , 255)
--note we are now using virtual width and height now for text placement
--draw welcome text on top of the screen
love.graphics.setFont(smallFont)
if gameState == 'start' then
love.graphics.printf('hello start state!', 0 , 20 , VIRTUAL_WIDTH , 'center' )
else
love.graphics.printf('hello play state!', 0 , 20 , VIRTUAL_WIDTH , 'center')
end
love.graphics.setFont(scoreFont)
love.graphics.print(tostring(player1Score),VIRTUAL_WIDTH / 2 - 50 , VIRTUAL_HEIGHT / 3)
love.graphics.print(tostring(player2Score),VIRTUAL_WIDTH / 2 + 30 , VIRTUAL_HEIGHT / 3)
player1:render()
player2:render()
ball:render()
--end rendering at virtual resolution
push:apply('end')
end
Ball.lua
code is:
--making a Ball class
Ball = Class{}
function Ball:init(x,y,width,height)
self.x=x
self.y=y
self.width=width
self.height=height
self.dy=math.random(2) ==1 and -100 or 100
self.dx=math.random(-50,50)
end
--[[places the ball in the middle of the screen with an
initial random velocity on both axes.]]
function Ball:reset()
self.x=VIRTUAL_WIDTH/2-2
self.y=VIRTUAL_HEIGHT/2-2
self.dy=math.random(2) == 1 and -100 or 100
self.dx=math.random(-50,50)
end
function Ball:update(dt)
self.x=self.x+self.dx * dt
self.y=self.y+self.dy * dt
end
function Ball:render()
love.graphics.rectangle('fill',self.x,self.y,self.width,self.height)
end
return Ball
plz help me on this matter.
Thanks in advance.
I had the same problem with the same CS50 course. I first had:
Class = require 'class'
push = require 'push'
require 'Ball'
require 'Paddle'
in main.lua and:
Paddle = class{}
in Paddle.lua.
I solved it by changing:
Class = require 'class'
to
require 'class'
and
Paddle = class{}
to
Paddle = class()
I had to read the readme from the class.lua library to figure it out.
Seems like you are on the tracks of the cs50 online course, I was having the same situation.
When I downloaded the distribution code, I saw that the class.lua file is not empty. When I changed the class.lua file with the file I have in my folder, problem was seemed to be solved.
Download the distribution code here
Related
edit: terrible mistake, just forgot to provide radius lol. Thanks for helping :)
I am so confused by this happening. I'm fairly certain all parts of my code work but for some reason, the x and y co-ordinates are not being printed by Love2D, despite showing them on screen and using type() to show that they're numbers.
function love.load()
window = {}
window.x, window.y = love.graphics.getDimensions()
enemies = {}
end
function newenemy()
x = math.random(0, window.x)
y = math.random(0, window.y)
table.insert(enemies, {x = x, y = y, speed = 5})
end
function love.update(dt)
newenemy()
for i=#enemies, 1, -1 do
local angle = math.atan((love.mouse.getY()-enemies[i]['y'])/(love.mouse.getX()-enemies[i]['x']))
if love.mouse.getX() < enemies[i]['x'] then angle = angle + math.pi end
enemies[i]['x'] = enemies[i]['x'] + math.cos(angle)*enemies[i]['speed']
enemies[i]['y'] = enemies[i]['y'] + math.sin(angle)*enemies[i]['speed']
end
end
function love.draw()
for i=1, #enemies do
love.graphics.print('('..enemies[i]['x']..','..enemies[i]['y']..')')
love.graphics.circle('fill', enemies[i]['x'], enemies[i]['y'])
end
end
To show the actual numbers, I've been commenting out the line to draw the circle and watching the numbers change as I move my cursor across the screen. I truly don't know what is going on. This code is from a much larger (~400 lines) script that I'm writing for and I thought there was some error with the variables but it still seems tp occur in 30 lines of code.
Error
main.lua:27: bad argument #4 to 'circle' (number expected, got no value)
Traceback
[C]: in function 'circle'
main.lua:27: in function 'draw'
[C]: in function 'xpcall'
Note the error
main.lua:27: bad argument #4
speaks of the fourth argument, wherein you are only providing three.
The fourth argument to love.graphics.circle is the radius of the circle.
love.graphics.circle('fill', enemies[i]['x'], enemies[i]['y'], 10)
I'm using LOVE2D and Lua for making games recently. I'm updating Breakout and I have an error in Paddle.lua.
Code:
Paddle = Class{}
--[[
Our Paddle will initialize at the same spot every time, in the middle
of the world horizontally, toward the bottom.
]]
size = math.random(4)
function Paddle:init(skin, size)
-- x is placed in the middle
self.x = VIRTUAL_WIDTH / 2 - 32
-- y is placed a little above the bottom edge of the screen
self.y = VIRTUAL_HEIGHT - 32
-- start us off with no velocity
self.dx = 0
self.size = size
self.height = 16
if self.size == 1 then
self.width = 32
elseif self.size == 3 then
self.width = 96
elseif self.size == 4 then
self.width = 128
else
self.width = 64
end
-- the skin only has the effect of changing our color, used to offset us
-- into the gPaddleSkins table later
self.skin = skin
end
function Paddle:update(dt)
-- keyboard input
if love.keyboard.isDown('left') then
self.dx = -PADDLE_SPEED
elseif love.keyboard.isDown('right') then
self.dx = PADDLE_SPEED
else
self.dx = 0
end
-- math.max here ensures that we're the greater of 0 or the player's
-- current calculated Y position when pressing up so that we don't
-- go into the negatives; the movement calculation is simply our
-- previously-defined paddle speed scaled by dt
if self.dx < 0 then
self.x = math.max(0, self.x + self.dx * dt)
-- similar to before, this time we use math.min to ensure we don't
-- go any farther than the bottom of the screen minus the paddle's
-- height (or else it will go partially below, since position is
-- based on its top left corner)
else
self.x = math.min(VIRTUAL_WIDTH - self.width, self.x + self.dx * dt)
end
end
--[[
Render the paddle by drawing the main texture, passing in the quad
that corresponds to the proper skin and size.
]]
function Paddle:render()
love.graphics.draw(gTextures['main'], gFrames['paddles'][self.size + 4 * (self.skin - 1)],
self.x, self.y)
end
Error:
Error
src/Paddle.lua:83: attempt to perform arithmetic on field 'size' (a nil value)
Traceback
src/Paddle.lua:83: in function 'render'
src/states/ServeState.lua:68: in function 'render'
src/StateMachine.lua:26: in function 'render'
main.lua:210: in function 'draw'
[C]: in function 'xpcall'
Saying that the value is nii even though I assigned it. How do I fix this?
Function parameters are local to the function's body. So inside Paddle.Init size is a local variable that shadows the global variable size.
As you call Paddle.Init without providing the size parameter, size is nil within the function leading to the observed error.
See Wikipedia: Variable Shadowing
Many people use a prefix to denote global variables. g_size for example. Then you could do something like:
g_size = 4
function Paddle:Init(skin, size)
self.size = size or g_size
end
Which would make self.size default to g_size if the size parameter is not provided.
Another option is to call the paddle constructor with your global size as input.
I am trying to move my hero in a multiplayer setup to the left and right.
I have to squares to initiate move left and move right for a regular crircle on a ground.
I am using AppWarp to initate the multiplayer instance and that is working fine, however I am having trouble on how to communicate the moving of the circle.
Here is my lua:
-- When left arrow is touched, move character left
function left:touch()
motionx = -speed;
end
left:addEventListener("touch",left)
-- When right arrow is touched, move character right
function right:touch()
motionx = speed;
end
right:addEventListener("touch",right)
-- Move character
local function movePlayer (event)
appWarpClient.sendUpdatePeers(tostring(player.x))
end
Runtime:addEventListener("enterFrame", movePlayer)
-- Stop character movement when no arrow is pushed
local function stop (event)
if event.phase =="ended" then
motionx = 0;
end
The keyline here is
appWarpClient.sendUpdatePeers(tostring(player.x))
with this I send the current X position of my hero (the circle) and in my warplisteners I pick it up like so:
function onUpdatePeersReceived(update)
local func = string.gmatch(update, "%S+")
-- extract the sent values which are space delimited
--local id = tostring(func())
local x = func()
statusText.text = x
player.x = x + motionx
end
When I start the game on 2 clients I can start moving the ball but it is wobbeling back and forth between 62 units, wich i guess is my speed
speed = 6; -- Set Walking Speed
if I change this:
function onUpdatePeersReceived(update)
local func = string.gmatch(update, "%S+")
-- extract the sent values which are space delimited
--local id = tostring(func())
local x = func()
statusText.text = x
player.x = x + motionx
end
to this:
function onUpdatePeersReceived(update)
local func = string.gmatch(update, "%S+")
-- extract the sent values which are space delimited
--local id = tostring(func())
local x = func()
statusText.text = x
player.x = player.x + motionx
end
(last line before "end")
player.x = player.x + motionx
instead of
player.x = x + motionx
The coordinates gets updated but the hero only moves on one of the screens.
Any idea how to implement a better movement system that moves my hero on both clients at the same time?
Kind regards
edit:
Added if-else, it was pending between +-speed and 0 since the speed is 0 when hero is stopped.
if(motionx ~= "0") then
player.x = player.x + motionx
statusText.text = "motionx ~= 0"
elseif(motionx == "0") then
player.x = player.x
else
statusText.text ="Something went horribly wrong"
end
Hi Everyone,
I would like know one thing :
I want to make this rectangle moving from the left side to the right side with physics and loop, and make it disappear when is out the leftscreen, and make reappear it in the right side,
This is what I've made in my code but I would like know if there is another easiest way to do it.
Is it better to use transition.to ?
Ps : My game is an endless runner game where the player jump from the floor to rectangles in the air
if someone have tutorial for this, I get it ! thank you
thanks every one for all
local physics = require( "physics" )
physics.start()
physics.setDrawMode( "hybrid")
local _x = display.contentCenterX
local _y = display.contentCenterY
local speed = 10
local GroupMur1 = display.newGroup()
local Mur1 = display.newRect(680,25,680,25)
Mur1.x = _x +900
Mur1.y = _y +80
physics.addBody(Mur1, "static")
GroupMur1:insert(Mur1)
local a =1
local function update ()
if(a==1)then updateMur1() end
if(a==2)then updateMur2() end
end
function updateMur1 ()
GroupMur1.x =GroupMur1.x - speed
if(GroupMur1.x < -2000) then
GroupMur1:remove(1)
a=2
end
end
function updateMur2()
GroupMur1:insert(Mur1)
physics.addBody(Mur1, "static")
GroupMur1.x = _x + 900
a=1
end
timer.performWithDelay(1, update, -1)
Well it's true that the transition.to is really useful and easy to use, but if you want to use physics, then use the applyLinearImpulse(), which is going to be easier if you want to use also collision detection. And once the rectangle is off screen, use the if and then function. It would be something like this:
if object.x > 500 then -- for example with a rectangle of 20 by 20
object.x = -20
end
To extend what #Fannick said, which should work by the way, the generic way to trigger this (for any object of any size) would be the code below. For this, I assume you have object.anchorX = 0 or object:setReferencePoint(display.CenterLeftReferencePoint) depending on your SDK version (the former is for v2 and the latter is for v1 - This link should help clear up differences)
--if the object is past the edge (screenOriginX used to scale for bigger devices)
if object.x > (display.contentWidth - display.screenOriginX) then
object.x = 0 + display.screenOriginX - object.contentWidth
end
If you have object.anchorX = 0.5 or object:setReferencePoint(display.CenterReferencePoint) (or haven't set either - both of these are the defaults) it would be:
if object.x > (display.contentWidth + (object.contentWidth/2) - display.screenOriginX) then
object.x = 0 + display.screenOriginX - (object.contentWidth/2)
end
For object.anchorX = 1 or object:setReferencePoint(display.CenterRightReferencePoint) it would be:
if object.x > (display.contentWidth + object.contentWidth - display.screenOriginX) then
object.x = 0 + display.screenOriginX
end
Hope you find the answer if you haven't already!
Cush
thanks both of you guy;
I've used the velocity to make the rectangle start to move and a collision to make 'em disappear
All your answers help me to understand better corona SDK !
I am working on a game in corona. I want to fire a bullet when a user swipes their finger on an object. The further he swipes, the further the the bullet should go. I worked on this and on tap event the bullet is fired, there are two functions start projectile and game loop, start projectile is used to fire projectile and game loop is used to translate the weapon, but I can't understand how to aim for the target using finger swipe. Please give me any suggestions, thanks...
Code for what has been achieved so far is below
local function startprojectile(event)
gameIsActive=true
local firetimer
local getobj=event.target
local getxloc=getobj.x
local getyloc=getobj.y
local function firenow()
if gameIsActive=false then
timer.cancel(firetimer)
firetimer=nil
else
local bullet=display.newImageRect("object.png",50,60);
bullet.x=getxloc-50; bullet.y=getyloc-50
bullet.type=bullet1
physics.addBody(bullet,{isSensor=true})
weaponGroup:insert(bullet)
end
gameIsActive=false
end
firetimer.timer.performWithDelay(650,firenow)
end
local function gameloop()
local i
for i=weaponGroup.numChildren,1,-1 do
local weapon=weaponGroup[i]
if weapon ~=nil and weapon.x ~=nil
then
weapon:translate(-20,0)
end
end
You can get the angle that the bullet should be fired by using the built in lua function
startX, startY = player.x, player.y
dir = math.atan2(( swipeY - player.y ), ( swipeX - player.x ))
bulletDx = bullet.speed * math.cos(dir)
bulletDy = bullet.speed * math.sin(dir)
table.insert( bullet, { x = startX, y = startY, dx = bulletDx, dy = bulletDy } )
You can change the variable from swipe Y to whatever Corona uses (I don't code with it).
I'm assuming you know how to move the bullet, but if not,
for i, v in ipairs( bullet ) do
bullet.x = bullet.x + bullet.dx * dt
bullet.y = bullet.y + bullet.dy * dt
end