Currently creating a game with Corona SDK is it possible to have an image and when it is clicked it displays 3 images and once one them 3 images are clicked the score increases by 1. Also Im only a beginner at coding , this is a new language to me. Thanks.
local CButton = display.newImage("+5.jpg" , 100 , 600)
CButton.alpha = 0.5
CButton.name = "CButton"
local CButtonLabel = display.newText( { text = "", x = 0, y = 0, fontSize = 28 } )
CButtonLabel:setTextColor( 0 ) ; CButtonLabel.x = 100 ; CButtonLabel.y = 45
local function touchCListener( event )
local object = event.target
print( event.target.name.." TOUCH on the '"..event.phase.."' Phase!" )
local ChordCOne = display.newImage("+5.jpg", 900,300)
local ChordCTwo = display.newImage("+5.jpg", 1000,300)
local ChordCThree = display.newImage("+5.jpg", 1100,300)
end
--add "touch" listener -- LABEL IS FOR TESTING!
CButton:addEventListener( "touch", touchCListener)
ChordCOne:addEventListener( "touch", updateScore)
CButtonLabel.text = "touch"
Yes, new DisplayObjects can be created in a listener function and listeners can be added to those objects as well.
In your code, you have not added the DisplayObjects created in your listener to any GroupObject (such as scene.view), which will give unexpected results.
Since the variables pointing to the newly created DisplayObjects (ChordCOne, etc.) are local to the function where they are instantiated, you cannot call addEventListener() on them outside the function. You should add the listener when they are created.
Also, the updateScore() listener function isn't defined anywhere. Make sure updateScore is not nil when and wherever you give it as an argument to addEventListener().
Related
This is an issue I come up against time and time again. I just can't get my head round it. This code was under create scene now I want to put it in a function with the idea of generated these blocks at different locations automatically through a loop. The errors I get are:
bad argument #1 in newRect (number expected) - 1st line.
sceneGroup is a nil value.
The solutions I have tried are:
1) defining sceneGroup at top of script. But then I get error that upvalue is a nil value.
2) defining it immediately before. - nil value.
If someone could explain this to me I would be very grateful. I keep getting problems like this.
local Backgroundrectangle = display.newRect(sceneGroup, 75, 75, display.contentWidth-150, display.contentHeight/2 )
Backgroundrectangle.isVisible = false
Backgroundrectangle.anchorX = 0
Backgroundrectangle.anchorY = 0
aAbackground = display.newRoundedRect(sceneGroup, Backgroundrectangle.x, Backgroundrectangle.y, 100, 125, 10 )
sceneGroup:insert(aAbackground)
aAbackground.id = "a"
aAbackground.strokeWidth = 2
aAbackground:setFillColor( gradient )
aAbackground:setStrokeColor( 0.2 )
aAmenutext = display.newText( "Aa", 100, 200, "Comic Sans MS", 50)
aAmenutext.x = aAbackground.x
aAmenutext.y = aAbackground.y - aAbackground.height/6
aAmenutext:setFillColor( 0.2 )
sceneGroup:insert(aAmenutext)
"Upvalue is nil" means the Runtime expects sceneGroup to be a local defined outside the scope of the function, but this is not the usual way of doing this in Corona.
If you have this
local composer = require( "composer" )
local scene = composer.newScene()
at the top of your Lua file for the scene, whenever you want to add a DisplayObject to the scene's GroupObject (possibly in your scene:create() method), you can declare
local sceneGroup = scene.view
and then use sceneGroup as you have been. scene will be defined (it has file scope) and the view property gives you the scene's GroupObject.
I am currently trying to work out how I should go about shooting projectiles using Corona SDK. However, I don't know the best way to go about doing this. I am guessing that you have to spawn instances of the same object and apply force to them but I don't know the best way to do it or how I should handle each instance. I am still learning Lua and just need some guidance on how to do it, any help will be appreciated.
I want to be able to check if any of the bullets hit a sensor object ( I haven't implemented this but I know how to ) at the top of the screen and then destroy the bullet that hit the sensor but how do I check each instance and destroy them individually?
This is the basic structure that I have so far.
display.setStatusBar( display.HiddenStatusBar )
local physics = require( 'physics' )
physics.start()
local speed = -500
local contentW, contentH = display.contentWidth, display.contentHeight
-- Background
local bg = display.newRect( 0, 0, contentW, contentH )
bg.anchorX = 0
bg.anchorY = 0
bg:setFillColor( 0, 1, 1 )
-- Ground
local ground = display.newRect( 0, contentH - 50, contentW, 50 )
ground.anchorX = 0
ground.anchorY = 0
ground:setFillColor( 0, 0.8, 0 )
-- Hero
local hero = display.newRect( contentW / 2, contentH / 2, 40, 40 )
hero:setFillColor( 1, 0, 0 )
function shoot( event )
if ( event.phase == 'began' ) then
local projectile = display.newRect( hero.x, hero.y, 10, 30 )
physics.addBody( projectile, 'dynamic' )
projectile.gravityScale = 0
projectile.isBullet = true
projectile:setLinearVelocity( 0, -600 )
end
end
Runtime:addEventListener( 'touch', shoot )
This was suggested on the Corona forums by the Corona staff.
To remove each bullet that hits the sensor you need to give the projectile a 'type' of something along those lines. Note that you can use any word instead of 'type', but this is my preferred way.
projectile.type = 'bullet'
Then, you need to add an event listener to the sensor object that detects the collision, in this case it is an object called 'wall'. On collision you want to remove the other object that was in the collision ( the bullet ). You can do this like so.
local function wallCollision( event )
if event.phase == 'began' then
if event.other.type == 'bullet' then
display.remove( event.other )
event.other = nil
end
end
end
wall:addEventListener( 'collision', wallCollision )
'event.other' targets the other object involved in the collision event, in this case, the 'bullet'.
Not sure this is what you are after, but the strategy to handle evolving multiple objects which can be removed later as a result of collision is:
create the bullet display object, with a collision handler
in the collision handler, if object needs to be removed then use removeSelf; other changes may require delayed change as explained in Modifying Objects.
So in your shoot function you would add, after projectile:setLinearVelocity:
projectile.collision = function (event)
...
if remove then
self:removeSelf()
end
...
end
projectile:addEventListener( "collision", projectile)
This adds the handler to each bullet. You could instead add just one handler for the sensor, it would be similar code which you would put right after creating the sensor, except that you remove the event.other instead of self:
sensor.collision = function (event)
...
if remove then
event.other:removeSelf()
end
...
end
sensor:addEventListener( "collision", sensor)
I make an endless run game using Corona SDK and I need to make a character selection between 2 characters (boy/girl). I don't have any idea how I should start.
I tried to make 2 portraits of the character on the menu screen, but I don't know what to do on Event Touch on them. I tried to save them in a variable but I don't know how to load them in the game.lua. There I have:
local spriteSheet = sprite.newSpriteSheet("monsterSpriteSheet.png", 100, 100)
local monsterSet = sprite.newSpriteSet(spriteSheet, 1, 7)
sprite.add(monsterSet, "running", 1, 6, 600, 0)
sprite.add(monsterSet, "jumping", 7, 7, 1, 1)
local monster = sprite.newSprite(monsterSet)
monster:prepare("running")
monster:play()
monster.x = 60
monster.y = 200
monster.gravity = -6
monster.accel = 0
monster.isAlive = true
I've got a main.lua a menu.lua and a game.lua. I use director class for transition. Any ideas on how I can do this?
You can pass parameters through storyboard.gotoScene
local options = {
effect = "crossFade",
time = 500,
params = {
character = myCharacter,
}
}
storyboard.gotoScene( "game", options )
and in the game.lua
function scene:createScene( event )
local params = event.params
local character = params.character
end
You could also create a data file and point to that file.
For example:
data.lua
local data = {}
return data
Then in your selection scene require data.lua and save your chosen character to it.
data.chosenCharacter = chosenCharater
Then in your game scene require data.lua again and point your character to what is saved in data.
local character = data.chosenCharacter
I am attempting to add/remove objects from the physics engine (addBody() and removeBody()) in an app I am working on. The app I am working on is modular so the issue is in one of two files.
The objects file (TransmitterObject) or the main file (main):
This is the relevant code for both:
main.lua
local physics = require("physics")
physics.start()
physics.setGravity(0,0)
physics.setDrawMode( "debug" )
local TransmitterObject = require("TransmitterObject")
function updateGame(event)
if(ITERATIONS % 100 == 0) then
tran1:activate() --create new physics object here
end
ITERATIONS = ITERATIONS + 1
--print(ITERATIONS)
end
Runtime:addEventListener("enterFrame", updateGame)
TransmitterObject.lua
function transmitter.new(props) --constructor
Transmitter =
{
x = props.x,
y = props.y,
receivers = props.receivers
}
return setmetatable( Transmitter, transmitter_mt )
end
function transmitter:activate()
local group = math.random(1, #self.receivers)
local receiver = math.random(1,#self.receivers[group])
local x , y = self.receivers[group][receiver][1], self.receivers[group][receiver][2]
local d = math.sqrt(math.pow((self.x-x),2) + math.pow((self.y-y),2))
local dx = math.abs(self.x - x)
local angle = math.deg(math.acos(dx/d))
local beam = display.newRect(self.x,self.y, d, 10)
beam:setReferencePoint(display.TopLeftReferencePoint)
beam.rotation = 180 + angle
beam:setFillColor(0,255,0)
beam.alpha = 0
local function add(event)
physics.addBody(beam, "static")
end
local function delete(event)
physics.removeBody(beam)
end
transition.to( beam, { time=1000, alpha=1.0, onComplete=add } )
transition.to( beam, { time=1000, delay=2500, alpha=0, onComplete=delete})
end
Now let me try to describe the issue a little better. basically every 100th time that 'enterFrame' fires I tell the transmitter object (tran1) to call its function 'activate'
which then preforms some basic math to get coordinates. Then it creates a rectangle (beam) using the calculated information and sets some properties. That is all basic stuff. Next I tell it to transition from not visible (alpha = 0) to visible over the span of 1 second. When does it is to call the function 'add' which adds the object to the physics engine. Likewise with the next line where it removes the objects.
That being said, when i set physics.setDrawMode( "debug" ) the beam object appears as a static body, but does not accept collisions. Does anyone know why the above code would not accept collisions for the beam object?
Keep in mind I have other objects that do work properly within the physics engine.
Wow, I'm answering super late!
On collisions, modifying bodies aren't supported.
What I propose you is to create a new function,
local function addBody ( event )
physics.addBody(ball, "static")
end
and in your collision event you have to add this,
timer.performWithDelay(500, addBody)
The only thing that may cause some problems it's the delay, but as the collision doesn't take too much time it should be ok.
Sorry for this necroposting,
It's just to help other people that may have that problem,
Fannick
I'm currently making a tower defense game with Corona SDK. However, while I'm making the gaming scene, The background scene always cover the monster spawn, I've tried background:toBack() ,however it's doesn't work.Here is my code:
module(..., package.seeall)
function new()
local localGroup = display.newGroup();
local level=require(data.levelSelected);
local currentDes = 1;
monsters_list = display.newGroup()
--The background
local bg = display.newImage ("image/levels/1/bg.png");
bg.x = _W/2;bg.y = _H/2;
bg:toBack();
--generate the monsters
function spawn_monster(kind)
local monster=require("monsters."..kind);
newMonster=monster.new()
--read the spawn(starting point) in level, and spawn the monster there
newMonster.x=level.route[1][1];newMonster.y=level.route[1][2];
monsters_list:insert(newMonster);
localGroup:insert(monsters_list);
return monsters_list;
end
function move(monster,x,y)
-- Using pythagoras to calauate the moving distace, Hence calauate the time consumed according to speed
transition.to(monster,{time=math.sqrt(math.abs(monster.x-x)^2+math.abs(monster.y-y)^2)/(monster.speed/30),x=x, y=y, onComplete=newDes})
end
function newDes()
currentDes=currentDes+1;
end
--moake monster move according to the route
function move_monster()
for i=1,monsters_list.numChildren do
move(monsters_list[i],200,200);
print (currentDes);
end
end
function agent()
spawn_monster("basic");
end
--Excute function above.
timer2 = timer.performWithDelay(1000,agent,10);
timer.performWithDelay(100,move_monster,-1);
timer.performWithDelay(10,update,-1);
move_monster();
return localGroup;
end
and the monster just stuck at the spawn point and stay there.
but, When i comment these 3 lines of code:
--local bg = display.newImage ("image/levels/1/bg.png");
--bg.x = _W/2;bg.y = _H/2;
--bg:toBack();
The problem disappear
Any ideas??Thanks for helping
Since you are using director, you should insert all your display objects into the localGroup.
You haven't inserted bg into localGroup.
SO director class inserts bg finally after inserting localGroup.
Modify your code as
--The background
local bg = display.newImage (localGroup,"image/levels/1/bg.png");
bg.x = _W/2;bg.y = _H/2;
bg:toBack();
or add the code
localGroup:insert(bg)
In more recent versions of Corona SDK:
Composer is the official scene (screen) creation and management library in Corona SDK.... The primary object in the Composer library is the scene object...and it contains a unique self.view.... This self.view is where you should insert visual elements pertaining to the scene.
So now in your scene:create() method, you should insert all DisplayObjects into self.view. It looks like this:
local composer = require( "composer" )
local scene = composer.newScene()
function scene:create()
local sceneGroup = self.view
local bg = display.newImage( ...
bg.x, bg.y = ...
local dude = display.newImage( ...
dude.x, dude.y = ....
sceneGroup:insert(bg)
sceneGroup:insert(dude)
end
The layering of DisplayObjects in this sceneGroup depends on the order in which they are added to the group, with the object added last on top. You can control this ordering with the toBack() and toFront() methods.