Jump to content

[TOPIC: topicViewTemplate]
[GLOBAL: userSmallPhoto]
Photo

Any threads on how to make a score counter for every "dodge"
Started by Davy1222 Oct 17 2018 06:03 PM

22 replies to this topic
[TOPIC CONTROLS]
[/TOPIC CONTROLS]
[modOptionsDropdown]
[/modOptionsDropdown]
[reputationFilter]
[TOPIC: post.html]
#1

Davy1222

[GLOBAL: userInfoPane.html]
Davy1222
  • Observer

  • 23 posts
  • Corona SDK

Ok so for my game, the last thing I need is a score and best score feature. The score is supposed to go up every time a collision doesn't happen/when my penguin dodges an ice block. For the most part I can only find tutorials on how to make the score go up every time you tap, so are there any tutorials for what I need? Also any tutorials on how to save the score and display the best score?



[TOPIC: post.html]
#2

XeduR @Spyric

[GLOBAL: userInfoPane.html]
XeduR @Spyric
  • Contributor

  • 293 posts
  • Corona SDK

You just need another trigger to count those dodges.

For instance, you could add an invisible circle behind the penguin. Then you track the "ended" phase for collisions with that circle and those ice blocks. If a collision ends and the penguin itself doesn't get hit, then the ice block only touched the circle, i.e. the penguin dodged it.

The best practice would probably be to display the score as a text on the screen. Whenever a new dodge occurs, you simply update the text to match the new score. For a tutorial on this, you could check out https://docs.coronalabs.com/tutorial/games/keepScores/index.html to get started. If you just want to save the top score, then perform a simple check to see if "current score > highscore" and then save it, etc.


  • roaminggamer likes this

[TOPIC: post.html]
#3

SGS

[GLOBAL: userInfoPane.html]
SGS
  • Corona Geek

  • 1,878 posts
  • Corona SDK

Simply increase score per move (distance travelled or whatever) and do not increase if a hit occurred (in that move).



[TOPIC: post.html]
#4

Davy1222

[GLOBAL: userInfoPane.html]
Davy1222
  • Observer

  • 23 posts
  • Corona SDK

You just need another trigger to count those dodges.

For instance, you could add an invisible circle behind the penguin. Then you track the "ended" phase for collisions with that circle and those ice blocks. If a collision ends and the penguin itself doesn't get hit, then the ice block only touched the circle, i.e. the penguin dodged it.

The best practice would probably be to display the score as a text on the screen. Whenever a new dodge occurs, you simply update the text to match the new score. For a tutorial on this, you could check out https://docs.coronalabs.com/tutorial/games/keepScores/index.html to get started. If you just want to save the top score, then perform a simple check to see if "current score > highscore" and then save it, etc.

i attempted this and my bar behind the penguin moves and causes a restart cause it hits the floor

my collision function is

local function onCollision(event)
	if event.phase == "began" then
		print "collide"
		-- applyForceToPenguin = false
		composer.gotoScene( "restart",{ time=800, effect="crossFade" } )
	end
end

is there a way to create a separate collision function for the bar that'll cause the score to go up



[TOPIC: post.html]
#5

XeduR @Spyric

[GLOBAL: userInfoPane.html]
XeduR @Spyric
  • Contributor

  • 293 posts
  • Corona SDK

Yes, you can create a separate collision function, you'd create it like you just created the one above, but that might not be necessary. Also, you are referring to very specific things in your code. Code, that no one of use can see, and so I don't know what "your bar" is.

In your collision function, you are currently only tracking if a collision began, regardless of what objects actually collided. You should read through https://docs.coronalabs.com/guide/physics/collisionDetection/index.html. In this case, you'd most likely want to add some identifier to your objects, as explained in the collision handling part of the docs. This way, you could can place that gotoScene inside an if statement so that it only runs if two specific objects collide.



[TOPIC: post.html]
#6

Davy1222

[GLOBAL: userInfoPane.html]
Davy1222
  • Observer

  • 23 posts
  • Corona SDK

Yes, you can create a separate collision function, you'd create it like you just created the one above, but that might not be necessary. Also, you are referring to very specific things in your code. Code, that no one of use can see, and so I don't know what "your bar" is.

In your collision function, you are currently only tracking if a collision began, regardless of what objects actually collided. You should read through https://docs.coronalabs.com/guide/physics/collisionDetection/index.html. In this case, you'd most likely want to add some identifier to your objects, as explained in the collision handling part of the docs. This way, you could can place that gotoScene inside an if statement so that it only runs if two specific objects collide.

 

I read through your link and I get that I'm supposed to be focused on multi-element collisions but I'm still not sure what to do. Specifically, how would I add identifiers to my objects and how would I change my collision function to only work for one specific object?



[TOPIC: post.html]
#7

XeduR @Spyric

[GLOBAL: userInfoPane.html]
XeduR @Spyric
  • Contributor

  • 293 posts
  • Corona SDK

You could do something like this:

 

local penguin = display.newRect(80,80,16,16)
penguin.x, penguin.y = display.contentCenterX, display.contentCenterY
penguin.id = "penguin"

physics.addBody( penguin, "dynamic",
    { friction=0.2, bounce=0.4 },
    { friction=0.2, bounce=0.4, radius=30, isSensor=true }
)

The first body belongs to the penguin and the latter to its sensor. If you are using id in your collision function, you can just include it like usual. Whenever a collision begins, ends, etc. you'll get the usual information in your collision function for all elements of the body. You can differentiate between the specific elements by using "event.selfElement". They are integers that correspond the table elements, i.e. 1 is the first element in the table, 2 is the second, etc.

 

So, if you type in print(event.selfElement) and you receive 2, it means that the sensor collided and not the penguin.

 

You can read more about them at https://docs.coronalabs.com/tutorial/games/multiElementCollision/index.html.



[TOPIC: post.html]
#8

Davy1222

[GLOBAL: userInfoPane.html]
Davy1222
  • Observer

  • 23 posts
  • Corona SDK

You could do something like this:

 

local penguin = display.newRect(80,80,16,16)
penguin.x, penguin.y = display.contentCenterX, display.contentCenterY
penguin.id = "penguin"

physics.addBody( penguin, "dynamic",
    { friction=0.2, bounce=0.4 },
    { friction=0.2, bounce=0.4, radius=30, isSensor=true }
)

The first body belongs to the penguin and the latter to its sensor. If you are using id in your collision function, you can just include it like usual. Whenever a collision begins, ends, etc. you'll get the usual information in your collision function for all elements of the body. You can differentiate between the specific elements by using "event.selfElement". They are integers that correspond the table elements, i.e. 1 is the first element in the table, 2 is the second, etc.

 

So, if you type in print(event.selfElement) and you receive 2, it means that the sensor collided and not the penguin.

 

You can read more about them at https://docs.coronalabs.com/tutorial/games/multiElementCollision/index.html.

 

Is there a certain way to reference the id in the collision function



[TOPIC: post.html]
#9

XeduR @Spyric

[GLOBAL: userInfoPane.html]
XeduR @Spyric
  • Contributor

  • 293 posts
  • Corona SDK

Is there a certain way to reference the id in the collision function

Yes. Read https://docs.coronalabs.com/guide/physics/collisionDetection/index.html#local-collision-handling



[TOPIC: post.html]
#10

Davy1222

[GLOBAL: userInfoPane.html]
Davy1222
  • Observer

  • 23 posts
  • Corona SDK

 

Ok I somewhat got it to work to the point where it won't restart if the bar hits the ground or ice, but now the ice pushes the bar off screen xD

 

this is my code for the bar

scorebar = display.newImage(sceneGroup, "scorecounter.png", 15, 250)
		physics.addBody(scorebar, "dynamic", {density=.1, bounce=0.1, friction=.5})

Is there a physics property I'm missing to make the ice go through the bar but still acknowledge the collision?



[TOPIC: post.html]
#11

XeduR @Spyric

[GLOBAL: userInfoPane.html]
XeduR @Spyric
  • Contributor

  • 293 posts
  • Corona SDK

That's already been answered and it is getting silly that I'm just pointing you to the same docs over and over again: https://docs.coronalabs.com/api/type/Body/isSensor.html. :P



[TOPIC: post.html]
#12

Davy1222

[GLOBAL: userInfoPane.html]
Davy1222
  • Observer

  • 23 posts
  • Corona SDK

That's already been answered and it is getting silly that I'm just pointing you to the same docs over and over again: https://docs.coronalabs.com/api/type/Body/isSensor.html. :P

oh sorry man it's a lot of info and it does get a little confusing what I am and am not doing



[TOPIC: post.html]
#13

XeduR @Spyric

[GLOBAL: userInfoPane.html]
XeduR @Spyric
  • Contributor

  • 293 posts
  • Corona SDK

Don't worry about it. :D

It is just getting silly, that's all. :P



[TOPIC: post.html]
#14

Davy1222

[GLOBAL: userInfoPane.html]
Davy1222
  • Observer

  • 23 posts
  • Corona SDK

Don't worry about it. :D

It is just getting silly, that's all. :P

Hello again, I've been trying for a week now but the collision function only works if I add the setLinearVelocity property to the scorebar and it doesn't allow me to set it to 0. If I set it to 0 there isn't an indication of a collision in the console and the score doesn't go up. Sorry for the bombardment of questions I'm just not sure what else to do at this point. 

 

My collision

local function onLocalCollision(event)
	if event.phase == "began" then

		print "collide2"
		score.add( .5 )
		print(event.selfElement) 
	end
end

The scorebar


	scorebar = display.newImage(sceneGroup, "scorecounter.png", 15, 250)
	scorebar.id = "scorebar"
		physics.addBody(scorebar, "dynamic")
		scorebar.gravityScale = 0
		scorebar.isSensor = true
		scorebar:setLinearVelocity( 0,0 ) 


[TOPIC: post.html]
#15

XeduR @Spyric

[GLOBAL: userInfoPane.html]
XeduR @Spyric
  • Contributor

  • 293 posts
  • Corona SDK

It would be useful if you could share more of your project that demonstrates your problem. It is really difficult to grasp the issue from what you've described now. If you don't want to share code that illustrates your problem, then please try to at least be more descriptive and add some visual aid, like a screenshot.



[TOPIC: post.html]
#16

Davy1222

[GLOBAL: userInfoPane.html]
Davy1222
  • Observer

  • 23 posts
  • Corona SDK

It would be useful if you could share more of your project that demonstrates your problem. It is really difficult to grasp the issue from what you've described now. If you don't want to share code that illustrates your problem, then please try to at least be more descriptive and add some visual aid, like a screenshot.

 

it wouldn't let me upload an image but this is my entire code 

display.setStatusBar(display.HiddenStatusBar)

local _W = display.contentWidth
local _H = display.contentHeight
local scrollSpeed = 3

local physics = require "physics"
physics.start()

local composer = require( "composer" )
local scene = composer.newScene()


--20 here you declare all your local variables:
local score = 0

--23 here you declare all your local functions:  -- whatever your code requires...


local function move(event)
	bg2.x = bg2.x - scrollSpeed/2
	bg3.x = bg3.x - scrollSpeed/2
	bg4.x = bg4.x - scrollSpeed/2
	bg5.x = bg5.x - scrollSpeed/2
	bg6.x = bg6.x - scrollSpeed/2
	bg7.x = bg7.x - scrollSpeed
	bg8.x = bg8.x - scrollSpeed
	bg9.x = bg9.x - scrollSpeed
	bg10.x = bg10.x - scrollSpeed
	bg11.x = bg11.x - scrollSpeed

	if(-bg2.x + bg2.contentWidth) > 1080 then
		bg2:translate(2000,0)
	end
	if(-bg3.x + bg3.contentWidth) > 1080 then
		bg3:translate(2000,0)
	end
	if(-bg4.x + bg4.contentWidth) > 1080 then
		bg4:translate(2000,0)
	end
	if(-bg5.x + bg5.contentWidth) > 1080 then
		bg5:translate(2000,0)
	end
	if(-bg6.x + bg6.contentWidth) > 1080 then
		bg6:translate(2000,0)
	end
	if(-bg7.x + bg7.contentWidth) > 1080 then
		bg7:translate(2000,0)
	end
	if(-bg8.x + bg8.contentWidth) > 1080 then
		bg8:translate(2000,0)
	end
	if(-bg9.x + bg9.contentWidth) > 1080 then
		bg9:translate(2000,0)
	end
	if(-bg10.x + bg10.contentWidth) > 1080 then
		bg10:translate(2000,0)
	end
	if(-bg11.x + bg11.contentWidth) > 1080 then
		bg11:translate(2000,0)
	end
end




local score = require( "score" )



local scoreText = score.init(
{
    fontSize = 40,
    x = 130,
    y = 30,
    maxDigits = 7,
    leadingZeros = false
})



local function isValidPhysics( obj )
   return( obj and type(obj.applyForce) == "function" )
end

local animation -- Leave it nil

local function activateAnimations(event)
   if( isValidPhysics( animation )) then
      animation:applyForce(0, -45, animation.x, animation.y)
   end
end

-- local peng = {}

-- local function activatePengs(event)
	-- peng:applyForce(0, -45, peng.x, peng.y)

-- end

local function touchScreen(event)
--107 print("touch")
	if event.phase == "began" then
		animation.enterFrame = activateAnimations
		Runtime:addEventListener("enterFrame", animation)
	end

	if event.phase == "ended" then
		Runtime:removeEventListener("enterFrame", animation)
	
	end

end


local function onCollision(event)
	if event.phase == "began" then
		print "collide"
		-- applyForceToPenguin = false
		composer.gotoScene( "restart",{ time=800, effect="crossFade" } )
		print(event.selfElement) 
	end
end

local function onLocalCollision(event)
	if event.phase == "began" then

		print "collide2"
		score.add( .5 )
		print(event.selfElement) 
	end
end

--now comes four required functions for Composer:

function scene:create( event )

local sceneGroup = self.view

    --129 put any thing you need to create here
	bg1 = display.newImageRect(sceneGroup, "bg.png", 800, 1000)

	bg2 = display.newImage(sceneGroup, "ice2.png",140,210)

	bg3 = display.newImage(sceneGroup, "ice2.png",540,210)

	bg4 = display.newImage(sceneGroup, "ice2.png",940,210)

	bg5 = display.newImage(sceneGroup, "ice2.png",1340,210)

	bg6 = display.newImage(sceneGroup, "ice2.png",1740,210)

	bg7 = display.newImage(sceneGroup, "ice1.png",140,420)

	bg8 = display.newImage(sceneGroup, "ice1.png",540,420)

	bg9 = display.newImage(sceneGroup, "ice1.png",940,420)

	bg10 = display.newImage(sceneGroup, "ice1.png",1340,420)

	bg11 = display.newImage(sceneGroup, "ice1.png",1740,420)

	ceiling = display.newImage(sceneGroup, "invisibleTile.png", 0, -120)
		physics.addBody(ceiling, "static", {density=.1, bounce=0.1, friction=.5})

	theFloor = display.newImage(sceneGroup, "invisibleTile.png", 0, 600)
		physics.addBody(theFloor, "static", {density=.1, bounce=0.1, friction=.5})

	scorebar = display.newImage(sceneGroup, "scorecounter.png", 15, 250)
	scorebar.id = "scorebar"
		physics.addBody(scorebar, "dynamic")
		scorebar.gravityScale = 0
		scorebar.isSensor = true
		scorebar:setLinearVelocity( 1,0 ) 


local sheetData = {
	width=50,
	height=28,
	numFrames=4,
	sheetContentWidth=200,
	sheetContentHeight=28

}

local mySheet = graphics.newImageSheet ( "pengs.png", sheetData )

local sequenceData = {

	{ name = "pengFly",
	  start = 1,
	  count = 4,
	  time = 400,
	  loopCount = 0,
	  loopDirection = "foward"
	 }

}

animation = display.newSprite(sceneGroup, mySheet, sequenceData)
	
animation.x = 80
animation.y = 201
animation.id = "animation"
	physics.addBody(animation, "dynamic", {density=.45, bounce=.1, friction=.5, radius=27},
	{bounce=.1, friction=.5, radius=27, isSensor = true})
animation:play()


	icebok = display.newImage(sceneGroup, "icebok.png", 480, 301)
		physics.addBody(icebok, "static", {density=.1, bounce=0.1, friction=.5, radius=10})
	icebok.speed = 4
	-- icebok.initY = icebok.y + math.random(0,500)
	-- icebok.amp = math.random(10,50)
	--157 icebok.angle = math.random(1,720)

	icebok1 = display.newImage(sceneGroup, "icebok.png", 680, 201)
		physics.addBody(icebok1, "static", {density=.1, bounce=0.1, friction=.5, radius=10})
	icebok1.speed =	4
	-- icebok1.initY = icebok1.y + math.random(0,500)
	-- icebok1.amp = math.random(10,50)
	-- icebok1.angle = math.random(1,720)

	icebok2 = display.newImage(sceneGroup, "icebok.png", 880, 301)
		physics.addBody(icebok2, "static", {density=.1, bounce=0.1, friction=.5, radius=10})
	icebok2.speed = 4
	-- icebok2.initY = icebok2.y + math.random(0,500)
	-- icebok2.amp = math.random(10,50)
	-- icebok2.angle = math.random(1,720)


	icebok3 = display.newImage(sceneGroup, "icebok.png", 1080, 401)
		physics.addBody(icebok3, "static", {density=.1, bounce=0.1, friction=.5, radius=10})
	icebok3.speed = 4
	-- icebok3.initY = icebok3.y + math.random(0,500)
	-- icebok2.amp = math.random(10,50)
	-- icebok2.angle = math.random(1,720)

	
	icebok4 = display.newImage(sceneGroup, "icebok.png", 1330, 499)
		physics.addBody(icebok4, "static", {density=.1, bounce=0.1, friction=.5, radius=10})
	icebok4.speed = 4
	-- icebok4.initY = icebok4.y + math.random(0,500)

	icebok5 = display.newImage(sceneGroup, "icebok.png", 1580, 499)
		physics.addBody(icebok5, "static", {density=.1, bounce=0.1, friction=.5, radius=10})
	icebok5.speed = 4
	-- icebok5.initY = icebok5.y + math.random(0,500)


	icebok6 = display.newImage(sceneGroup, "icebok.png", 1830, 401)
		physics.addBody(icebok6, "static", {density=.1, bounce=0.1, friction=.5, radius=10})
	icebok6.speed = 4
	-- icebok6.initY = icebok6.y + math.random(0,500)

	function moveiceboks(self,event)
		if self.x < -10 then
			self.x = math.random(480,1830)
			-- self.x = 480
			self.y = math.random(0,500)
			self.speed = 4
			-- self.amp = math.random(10,50)
			-- self.angle = math.random(1,720)

		else
			self.x = self.x - self.speed
			-- self.angle = self.angle + .1
			-- self.y = self.amp * math.tan(self.angle) + self.initY
			--196 self.y = math.random(0,500)
		end
	end
end


function scene:show( event )


     local sceneGroup = self.view
	if event.phase == "will" then
         -- put code here you want to happen just before the scene comes on the screen
	-- physics.start()

	Runtime:addEventListener("enterFrame", move)
	Runtime:addEventListener("touch", touchScreen)
	icebok.enterFrame = moveiceboks
	Runtime:addEventListener("enterFrame",icebok)
	icebok1.enterFrame = moveiceboks
	Runtime:addEventListener("enterFrame",icebok1)
	icebok2.enterFrame = moveiceboks
	Runtime:addEventListener("enterFrame",icebok2)
	icebok3.enterFrame = moveiceboks
	Runtime:addEventListener("enterFrame",icebok3)
	icebok4.enterFrame = moveiceboks
	Runtime:addEventListener("enterFrame",icebok4)
	icebok5.enterFrame = moveiceboks
	Runtime:addEventListener("enterFrame",icebok5)
	icebok6.enterFrame = moveiceboks
	Runtime:addEventListener("enterFrame",icebok6)
	animation.collision = onCollision
	animation:addEventListener("collision", onCollision)
	scorebar.collision = onLocalCollision
	scorebar:addEventListener("collision", onLocalCollision)


     	else
         -- put code here you want to happen after the scene comes on the screen
	-- physics.start()
	-- Runtime:addEventListener("enterFrame", move)
	Runtime:addEventListener("touch", touchScreen)

	-- icebok.enterFrame = moveiceboks
	-- Runtime:addEventListener("enterFrame",icebok)

	-- icebok1.enterFrame = moveiceboks
	-- Runtime:addEventListener("enterFrame",icebok1)

	-- icebok2.enterFrame = moveiceboks
	-- Runtime:addEventListener("enterFrame",icebok2)

	-- icebok3.enterFrame = moveiceboks
	-- Runtime:addEventListener("enterFrame",icebok3)
	animation.collision = onCollision
	animation:addEventListener("collision", onCollision)

	scorebar.collision = onLocalCollision
	scorebar:addEventListener("collision", onLocalCollision)

    end

end

function scene:hide( event )
    local sceneGroup = self.view
	if event.phase == "will" then
         -- put code here you want to happen just before the scene leaves the screen

	Runtime:removeEventListener("enterFrame", move)
	Runtime:removeEventListener("touch", touchScreen)
	
	-- icebok.enterFrame = moveiceboks
	Runtime:removeEventListener("enterFrame",icebok)

	-- icebok1.enterFrame = moveiceboks
	Runtime:removeEventListener("enterFrame",icebok1)
	
	-- icebok2.enterFrame = moveiceboks
	Runtime:removeEventListener("enterFrame",icebok2)

	-- icebok3.enterFrame = moveiceboks	
	Runtime:removeEventListener("enterFrame",icebok3)

	Runtime:removeEventListener("enterFrame",icebok4)

	Runtime:removeEventListener("enterFrame",icebok5)

	Runtime:removeEventListener("enterFrame",icebok6)

	animation:removeEventListener("collision", onCollision)

	scorebar:removeEventListener("collision", onLocalCollision)

-- composer.removeScene("game")

	else
         -- put code here you want to happen after the scene has left the screen

	-- Runtime:removeEventListener("enterFrame", move)

	Runtime:removeEventListener("touch", touchScreen)
	
	Runtime:removeEventListener("enterFrame",icebok)

	Runtime:removeEventListener("enterFrame",icebok1)
	
	Runtime:removeEventListener("enterFrame",icebok2)

	Runtime:removeEventListener("enterFrame",icebok3)

	Runtime:removeEventListener("enterFrame",icebok4)

	Runtime:removeEventListener("enterFrame",icebok5)

	Runtime:removeEventListener("enterFrame",icebok6)

	animation:removeEventListener("collision", onCollision)

	scorebar:removeEventListener("collision", onLocalCollision)

	physics.removeBody(peng, "dynamic", {density=.18, bounce=0.1, friction=.5, radius=55})
	-- physics.pause()

-- composer.removeScene("game")

	end

end

function scene:destroy( event )
     local sceneGroup = self.view

     -- put code here if you have things you need to remove that you created in create scene that does NOT go into the sceneGroup)

end

-- these must be the last 5 lines in the file
scene:addEventListener( "create", scene )
scene:addEventListener( "show", scene )
scene:addEventListener( "hide", scene )
scene:addEventListener( "destroy", scene )
return scene


[TOPIC: post.html]
#17

XeduR @Spyric

[GLOBAL: userInfoPane.html]
XeduR @Spyric
  • Contributor

  • 293 posts
  • Corona SDK

Hmm... there seems to be a lot going on and I believe that you could get by with a lot less. For instance, you seem to have a lot of runtime listeners and I'm not sure that you need them.

Here's a full code sample of what I've basically been talking about. Please let me know if this is anywhere close to what you have been trying to achieve. If it isn't, then please provide me with some images of what you want to do, accompanied with detailed explanations. We've both invested too much time here to let this be. :D

 

local physics = require("physics")
physics.setDrawMode( "hybrid" )
physics.start()

local penguin = display.newRect(display.contentCenterX,display.contentCenterY,16,16)
penguin.id = "penguin"

physics.addBody( penguin, "static",
    { friction=0.2, bounce=0.4 },							-- index #1
    { friction=0.2, bounce=0.4, radius=30, isSensor=true }	-- index #2
)

local projectile = {}
local shotCount = 1

local function delete(target)
	display.remove(target)
	target = nil
end

local function onLocalCollision(self,event)
	-- track the "ended" phase, so you'll know if the penguin itself was hit or if only the sensor was hit
	if ( event.phase == "ended" ) then
		if self.id == "penguin" then
			if event.selfElement == 1 then
				print("Projectile #"..event.other.shotNumber.." hit penguin.")
				-- penguin was hit, so gameover?

				-- deleting the projectile on collision
				display.remove(event.other)
				event.other = nil
			else
				print("Projectile #"..event.other.shotNumber.." missed the penguin.")
				-- the projectile was dodged, so increase the score

				timer.performWithDelay( 200, function() delete (event.other) end)	-- deleting the dodged projectile
			end
		end
	end
end

penguin.collision = onLocalCollision
penguin:addEventListener( "collision" )

local function shoot()
	projectile[#projectile+1] = display.newCircle(display.contentCenterX+160,display.contentCenterY-20,5)
	projectile[#projectile].shotNumber = shotCount
	physics.addBody( projectile[#projectile], "dynamic", {bounce=0.5, density=1, radius=projectile[#projectile].width*0.5})

	projectile[#projectile].collision = onLocalCollision
	projectile[#projectile]:addEventListener( "collision" )

	if shotCount % 5 == 0 then
		projectile[#projectile]:applyLinearImpulse( -1, -0.1, projectile[#projectile].x, projectile[#projectile].y )
	else
		projectile[#projectile]:applyLinearImpulse( -1, -0.25, projectile[#projectile].x, projectile[#projectile].y )
	end
	shotCount = shotCount+1
end

timer.performWithDelay( 1000, shoot, 0 )

 



[TOPIC: post.html]
#18

SGS

[GLOBAL: userInfoPane.html]
SGS
  • Corona Geek

  • 1,878 posts
  • Corona SDK

Wow this post keeps going on and on....

 

A simple solution to collision is to NOT use physics and use simple maths instead

    local function isCollision(object1, object2)
        obj1 = object1.contentBounds
        obj2 = object2.contentBounds
        if obj1 and obj2 then
            local left = obj1.xMin <= obj2.xMin and obj1.xMax >= obj2.xMin
            local right = obj1.xMin >= obj2.xMin and obj1.xMin <= obj2.xMax
            local up = obj1.yMin <= obj2.yMin and obj1.yMax >= obj2.yMin
            local down = obj1.yMin >= obj2.yMin and obj1.yMin <= obj2.yMax
            return ( left or right ) and ( up or down )
        else return false end
    end

Posting this for everyone really.... simply pass the above function 2 display objects and if they collide then they have hit and the function returns true.

 

Note: this uses simple box collisions and is meant for simple sprites.  However it works for most objects that can be bound by a simple rect.



[TOPIC: post.html]
#19

SGS

[GLOBAL: userInfoPane.html]
SGS
  • Corona Geek

  • 1,878 posts
  • Corona SDK

@davy1222 your code is so wasteful..  You really need to invest some time to understand arrays of objects.  It will make your code far more simple and readable.

 

For example, this code

local function move(event)
	bg2.x = bg2.x - scrollSpeed/2
	bg3.x = bg3.x - scrollSpeed/2
	bg4.x = bg4.x - scrollSpeed/2
	bg5.x = bg5.x - scrollSpeed/2
	bg6.x = bg6.x - scrollSpeed/2
	bg7.x = bg7.x - scrollSpeed
	bg8.x = bg8.x - scrollSpeed
	bg9.x = bg9.x - scrollSpeed
	bg10.x = bg10.x - scrollSpeed
	bg11.x = bg11.x - scrollSpeed

	if(-bg2.x + bg2.contentWidth) > 1080 then
		bg2:translate(2000,0)
	end
	if(-bg3.x + bg3.contentWidth) > 1080 then
		bg3:translate(2000,0)
	end
	if(-bg4.x + bg4.contentWidth) > 1080 then
		bg4:translate(2000,0)
	end
	if(-bg5.x + bg5.contentWidth) > 1080 then
		bg5:translate(2000,0)
	end
	if(-bg6.x + bg6.contentWidth) > 1080 then
		bg6:translate(2000,0)
	end
	if(-bg7.x + bg7.contentWidth) > 1080 then
		bg7:translate(2000,0)
	end
	if(-bg8.x + bg8.contentWidth) > 1080 then
		bg8:translate(2000,0)
	end
	if(-bg9.x + bg9.contentWidth) > 1080 then
		bg9:translate(2000,0)
	end
	if(-bg10.x + bg10.contentWidth) > 1080 then
		bg10:translate(2000,0)
	end
	if(-bg11.x + bg11.contentWidth) > 1080 then
		bg11:translate(2000,0)
	end
end

could be simplified to

local function move(event)
	for i = 1, 11 do
		if i < 7 then
			gb[i].x = gb[i].x - scrollSpeed/2
		else gb[i].x = gb[i].x - scrollSpeed end

		if(-bg[i].x + bg[i].contentWidth) > 1080 then
			bg[i]:translate(2000,0)
		end
	end
end


[TOPIC: post.html]
#20

XeduR @Spyric

[GLOBAL: userInfoPane.html]
XeduR @Spyric
  • Contributor

  • 293 posts
  • Corona SDK

Yeah, there's a lot to improve upon regarding the code.

As for SGS's math solution, it is a simpler method and it can easily be modified to work with circles as well. If your game doesn't require physics apart from the collision detection for the dodging itself, then opting to use a purely mathematical solution is better.



[TOPIC: post.html]
#21

SGS

[GLOBAL: userInfoPane.html]
SGS
  • Corona Geek

  • 1,878 posts
  • Corona SDK

For the benefit of others reading this....

 

Also, there is not a use case (realistically) that needs more than a single enterFrame event.



[TOPIC: post.html]
#22

Davy1222

[GLOBAL: userInfoPane.html]
Davy1222
  • Observer

  • 23 posts
  • Corona SDK

 

Hmm... there seems to be a lot going on and I believe that you could get by with a lot less. For instance, you seem to have a lot of runtime listeners and I'm not sure that you need them.

Here's a full code sample of what I've basically been talking about. Please let me know if this is anywhere close to what you have been trying to achieve. If it isn't, then please provide me with some images of what you want to do, accompanied with detailed explanations. We've both invested too much time here to let this be.  :D

 

local physics = require("physics")
physics.setDrawMode( "hybrid" )
physics.start()

local penguin = display.newRect(display.contentCenterX,display.contentCenterY,16,16)
penguin.id = "penguin"

physics.addBody( penguin, "static",
    { friction=0.2, bounce=0.4 },							-- index #1
    { friction=0.2, bounce=0.4, radius=30, isSensor=true }	-- index #2
)

local projectile = {}
local shotCount = 1

local function delete(target)
	display.remove(target)
	target = nil
end

local function onLocalCollision(self,event)
	-- track the "ended" phase, so you'll know if the penguin itself was hit or if only the sensor was hit
	if ( event.phase == "ended" ) then
		if self.id == "penguin" then
			if event.selfElement == 1 then
				print("Projectile #"..event.other.shotNumber.." hit penguin.")
				-- penguin was hit, so gameover?

				-- deleting the projectile on collision
				display.remove(event.other)
				event.other = nil
			else
				print("Projectile #"..event.other.shotNumber.." missed the penguin.")
				-- the projectile was dodged, so increase the score

				timer.performWithDelay( 200, function() delete (event.other) end)	-- deleting the dodged projectile
			end
		end
	end
end

penguin.collision = onLocalCollision
penguin:addEventListener( "collision" )

local function shoot()
	projectile[#projectile+1] = display.newCircle(display.contentCenterX+160,display.contentCenterY-20,5)
	projectile[#projectile].shotNumber = shotCount
	physics.addBody( projectile[#projectile], "dynamic", {bounce=0.5, density=1, radius=projectile[#projectile].width*0.5})

	projectile[#projectile].collision = onLocalCollision
	projectile[#projectile]:addEventListener( "collision" )

	if shotCount % 5 == 0 then
		projectile[#projectile]:applyLinearImpulse( -1, -0.1, projectile[#projectile].x, projectile[#projectile].y )
	else
		projectile[#projectile]:applyLinearImpulse( -1, -0.25, projectile[#projectile].x, projectile[#projectile].y )
	end
	shotCount = shotCount+1
end

timer.performWithDelay( 1000, shoot, 0 )

 

your code works similarly

 

 

 

 

but this is closer to what I'm trying to achieve outside of the bar moving forward

 

 

This happens when I use the code from the isSensor thread and set the linear velocity (1,0)

 

 

 

 

 

 

@davy1222 your code is so wasteful..  You really need to invest some time to understand arrays of objects.  It will make your code far more simple and readable.

 

For example, this code

local function move(event)
	bg2.x = bg2.x - scrollSpeed/2
	bg3.x = bg3.x - scrollSpeed/2
	bg4.x = bg4.x - scrollSpeed/2
	bg5.x = bg5.x - scrollSpeed/2
	bg6.x = bg6.x - scrollSpeed/2
	bg7.x = bg7.x - scrollSpeed
	bg8.x = bg8.x - scrollSpeed
	bg9.x = bg9.x - scrollSpeed
	bg10.x = bg10.x - scrollSpeed
	bg11.x = bg11.x - scrollSpeed

	if(-bg2.x + bg2.contentWidth) > 1080 then
		bg2:translate(2000,0)
	end
	if(-bg3.x + bg3.contentWidth) > 1080 then
		bg3:translate(2000,0)
	end
	if(-bg4.x + bg4.contentWidth) > 1080 then
		bg4:translate(2000,0)
	end
	if(-bg5.x + bg5.contentWidth) > 1080 then
		bg5:translate(2000,0)
	end
	if(-bg6.x + bg6.contentWidth) > 1080 then
		bg6:translate(2000,0)
	end
	if(-bg7.x + bg7.contentWidth) > 1080 then
		bg7:translate(2000,0)
	end
	if(-bg8.x + bg8.contentWidth) > 1080 then
		bg8:translate(2000,0)
	end
	if(-bg9.x + bg9.contentWidth) > 1080 then
		bg9:translate(2000,0)
	end
	if(-bg10.x + bg10.contentWidth) > 1080 then
		bg10:translate(2000,0)
	end
	if(-bg11.x + bg11.contentWidth) > 1080 then
		bg11:translate(2000,0)
	end
end

could be simplified to

local function move(event)
	for i = 1, 11 do
		if i < 7 then
			gb[i].x = gb[i].x - scrollSpeed/2
		else gb[i].x = gb[i].x - scrollSpeed end

		if(-bg[i].x + bg[i].contentWidth) > 1080 then
			bg[i]:translate(2000,0)
		end
	end
end

 

 

Yeaa I know my code is a bit messy, I was hoping it wouldn't be too obvious but I got a little excited when I found this app and got right into making the game instead of looking into lua.

Also my code needs physics for the touch function otherwise the penguin stays stationary. 

 

 

Also I appreciate you guys's help I know how frustrating it must be talking to someone who has no clue what they're doing.



[TOPIC: post.html]
#23

XeduR @Spyric

[GLOBAL: userInfoPane.html]
XeduR @Spyric
  • Contributor

  • 293 posts
  • Corona SDK

Alright, seems like I had a completely different idea of your game in my head. This is why visual aids are so great.

From what I can see, you could achieve all of that without the use of physics. Since those ice blocks aren't perfect rectangles, you'd sacrifice a bit of accuracy in terms of collision detection, but your game would be less resource heavy and it would require less code as a result.

For scoring, you currently have a large rect that detects when those ice blocks reach the left side of the screen, but you shouldn't use collision detection here. Just write an enterFrame function that loops through all ice blocks. If an ice block's x location is to the left of the penguin and it hasn't collided with the penguin, then obviously it was dodged. At this point, you'd add one point to the player (and you could stop tracking ice blocks that have yielded points already to make the function lighter). For detecting if an ice block collides with the penguin, you could use SGS's function.

As for the penguin remaining stationary, from the looks of it, you could just add a few lines of code to the enterFrame function to drag the penguin down if the player isn't touching the screen. If the player is touching the screen, then you'd move the penguin up.



Now, probably the reason as to why you need to move the scorebar in your code (as it is now), is if you move those iceblocks with transitions, then most likely the collisions don't occur. What you could do, if you want to stick to physics, is to do something along the lines of:
 

local physics = require("physics")
physics.setDrawMode( "hybrid" )
physics.start()

local iceblock, iceblockTransition = {}, {}

local function onLocalCollision( self, event )
    if ( event.phase == "began" ) then
		if self.name == "scorebar" then
	        print("Collision")
		end
    end
end

local scorebar = display.newRect(100,160,20,320)
physics.addBody( scorebar, "dynamic", {density=1, isSensor=true} )
scorebar.collision = onLocalCollision
scorebar.name = "scorebar"
scorebar.gravityScale = 0
scorebar:addEventListener( "collision" )
scorebar:setFillColor(0,1,1)

local function moveBlock()
	iceblock[#iceblock+1] = display.newRect(400,math.random(40,280),20,20)
	physics.addBody( iceblock[#iceblock], "kinematic" )
	iceblock[#iceblock].collision = onLocalCollision
	iceblock[#iceblock]:addEventListener( "collision" )
	iceblockTransition[#iceblockTransition+1] = transition.to( iceblock[#iceblock], {time=1500,x=0} )
end

local iceblockTimer = timer.performWithDelay( 500, moveBlock, 0 )

But, once again, I would advice against the use of physics in this case as you don't (at least yet) have anything that makes the use of physics compulsory.

Now, I hope that we've solved this issue, so that we can lay this thread to rest. :D




[topic_controls]
[/topic_controls]