To Trigger Animations At Certain Times - help?

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
worldaway
Prole
Posts: 44
Joined: Thu Sep 08, 2011 2:22 am

To Trigger Animations At Certain Times - help?

Post by worldaway » Sun May 27, 2012 5:08 am

I have a game, and I want it to work so that when you shoot an enemy, an explosion animation goes off at the position of the enemy (the enemy explodes). But I cant seem to get it right. I am using "AnAL" by the way.

This is the area of my code where I am guessing I have to print something to trigger the animation (in function updateGame):

Code: Select all

		-- check for collision with enemies
		for ii,vv in ipairs(enemies) do
			if CheckCollision(v.x,v.y,2,5,vv.x,vv.y,vv.width,vv.height) then
				--PRINT CODE HERE
				-- mark that enemy for removal
				table.insert(remEnemy, ii)
				-- mark the shot to be removed
				table.insert(remShot, i)				
				
			end
		end
Here is my whole code (above included):

Code: Select all

state = 0 -- 0 = menu, 1 = game, 2 = gameover, 3 = information

function start()

	require ("anal")
	
	hero = {}
	hero.x = 400
	hero.y = 300
	hero.width = 5
	hero.height = 25
	hero.speed = 300
	hero.shots = {} -- holds fired shots
	
	enemies = {}
	
		for i=0,6 do
			enemy = {}
			enemy.width = 40
			enemy.height = 30
			enemy.x = i * (enemy.width + 60) + 100
			enemy.y = enemy.height - 100 + math.random() * 30 * i   
			table.insert(enemies, enemy)
		end

	fastEnemies = {}
	
		for i=0,2 do
			fastEnemy = {}
			fastEnemy.width = 25
			fastEnemy.height = 38
			fastEnemy.x = i * (fastEnemy.width + 300) + 75
			fastEnemy.y = enemy.height - 100
			table.insert (fastEnemies, fastEnemy)
		end

		
		anim = newAnimation(img, 36, 36, 0.05, 0)
		anim:setMode ("once")
		
		scan = newAnimation(scanner, 36, 36, 0.05, 0)
		scan:setMode ("loop")
		
		sClock = newAnimation (clockSprite, 36, 36, 0.05, 0)
		sClock:setMode ("loop")

state = 1
end

function love.load()
				
   pigman = love.graphics.newImage("Resources/pigman.png")
   img = love.graphics.newImage ("Resources/explosion.png")
   enemyPic = love.graphics.newImage("Resources/enemy.png")
   fEnemyPic = love.graphics.newImage("Resources/fEnemy.png")
   backround = love.graphics.newImage ("Resources/backround.png")	
   menuPic = love.graphics.newImage ("Resources/menuPic.png")
   info = love.graphics.newImage ("Resources/info.png")
   Over = love.graphics.newImage ("Resources/Over.png")
   scanner = love.graphics.newImage ("Resources/scannersprite.png")
   clockSprite = love.graphics.newImage ("Resources/clock.png")
   Music = love.audio.newSource ("Resources/Music.mp3")
   woosh = love.audio.newSource ("Resources/woosh.mp3" , "static")
   Music:setLooping(Music)
   love.audio.play (Music)
   
end

function gameOver()
	state = 2
end

function information()
	state = 3
end

function spawnEnemies()

		for i=0,6 do
			enemy = {}
			enemy.width = 40
			enemy.height = 30
			enemy.x = i * (enemy.width + 60) + 100
			enemy.y = enemy.height - 100 + math.random() * 30 * i   
			table.insert(enemies, enemy)
		end


end

function spawnFastEnemies()

	for i=0,2 do
		fastEnemy = {}
		fastEnemy.width = 25
		fastEnemy.height = 38
		fastEnemy.x = i * (fastEnemy.width + 300) + 75
		fastEnemy.y = enemy.height - 100
		table.insert (fastEnemies, fastEnemy)
	end

end

spawntimer = 3
fSpawntimer = 7
timer = 1
pTimer = 1
score = pTimer

function updateGame(dt)

--spawn enemies every 3 seconds and 7 seconds

  spawntimer = spawntimer - dt
  
  if spawntimer <= 0 then
    spawnEnemies()
    local leftover = math.abs(spawntimer)
    spawntimer = 3 - leftover
  end
  
  fSpawntimer = fSpawntimer - dt	
	
  if fSpawntimer <= 0 then
     spawnFastEnemies()
	 local sLeftover = math.abs(fSpawntimer)
	 fSpawntimer = 7 - sLeftover
  end	
  
  timer = timer - dt
	
   if timer <= 0 then
	pTimer = pTimer + 1
	local tLeftover = math.abs(timer)
	timer = 1 - tLeftover
   end
  
  
  if # enemies + # fastEnemies >= 40 then
	state = 2
	end
	
  
  --update animations
	anim:update(dt)
	scan:update(dt)
	sClock:update(dt)
  
--keyboard actions (move hero)

	if love.keyboard.isDown("left") then            
		hero.x = hero.x - hero.speed*dt
	elseif love.keyboard.isDown("right") then
		hero.x = hero.x + hero.speed*dt
	elseif love.keyboard.isDown("up") then
		hero.y = hero.y - hero.speed*dt
	elseif love.keyboard.isDown("down") then
		hero.y = hero.y	+ hero.speed*dt
	end
	
		local remEnemy = {}
		local remShot = {}
		local remFastEnemy = {}
	
	-- update the shots
   for i,v in ipairs(hero.shots) do
		if v.dir == 1 then
			v.y = v.y - dt * 500
		elseif v.dir == 2 then
			v.x = v.x - dt * 500
		else
			v.x = v.x + dt * 500
		end
	
		-- mark shots that are not visible for removal
		if v.y < 0 then
			table.insert(remShot, i)
		end
		
		-- check for collision with enemies
		for ii,vv in ipairs(enemies) do
			if CheckCollision(v.x,v.y,2,5,vv.x,vv.y,vv.width,vv.height) then
				
				-- mark that enemy for removal
				table.insert(remEnemy, ii)
				-- mark the shot to be removed
				table.insert(remShot, i)				
				
			end
		end
		
		for ii,vv in ipairs(fastEnemies) do
			if CheckCollision(v.x,v.y,2,5,vv.x,vv.y,vv.width,vv.height) then
				--anim:draw (100,100)
				-- mark that enemy for removal
				table.insert(remFastEnemy, ii)
				-- mark the shot to be removed
				table.insert(remShot, i)				
				
			end
		end

		
	end	
	
	-- remove the marked enemies
	for i,v in ipairs(remEnemy) do
		table.remove(enemies, v)
	end
	
	for i,v in ipairs(remFastEnemy) do
		table.remove(fastEnemies, v)
	end

	
	for i,v in ipairs(remShot) do
		table.remove(hero.shots, v)
		
	end
	
	-- update enemies
	for i,v in ipairs(enemies) do
		-- fall down slowly
		v.y = v.y + 20*dt
				
	end
	
	for i,v in ipairs(fastEnemies) do
		-- fall down quickly
		v.y = v.y + 75*dt
				
	end
	
end

function love.mousereleased()
	if (state == 0) then
		start()
	end
end


function love.update(dt)
	if (state == 1) then
		updateGame(dt)
	end
end


function drawGame()
	love.graphics.setColor ( 255, 255, 255)
	love.graphics.draw(backround)
	
	--draw explosion animation
	anim:draw (100, 100)
	
	--draw scanner animation
	scan:draw (10, 550)
	
	--draw clock animation
	sClock:draw (750, 550)

	love.graphics.setColor(225,225,225,225)

	love.graphics.rectangle("fill", hero.x, hero.y, hero.width, hero.height)
	love.graphics.draw(pigman, hero.x-36, hero.y+5, hero.width/25, hero.height/25) 

		-- draw heros shots
	love.graphics.setColor(255,255,255,255)
	for i,v in ipairs(hero.shots) do
		love.graphics.rectangle("fill", v.x, v.y, 2, 2)
	end
	
	-- draw enemies
	for i,v in ipairs(enemies) do
		love.graphics.draw(enemyPic, v.x+25, v.y-15, v.width/35, v.height/35)
	end
	
	for i,v in ipairs(fastEnemies) do
		love.graphics.draw(fEnemyPic, v.x+20, v.y-15, v.width/38, v.height/38)
	end
	love.graphics.setColor (0, 0, 0)
	love.graphics.print(# enemies + # fastEnemies, 20, 560)
	love.graphics.print (pTimer, 762, 560)
	
	love.graphics.setColor (255, 255, 255)
	love.graphics.print("Beta 1.2 ", 10, 10)

	score = pTimer

end

function drawMenu()
	love.graphics.draw (menuPic)
end

function drawInformation()
	love.graphics.draw (info)
end

function drawGameOver()
	love.graphics.draw (Over)
	love.graphics.print ("Score:", 340, 350)
	love.graphics.print (score, 410, 350)
end

function love.draw()
	if (state == 0) then drawMenu() end
	if (state == 1) then drawGame() end
	if (state == 2) then drawGameOver() end
	if (state == 3) then drawInformation() end
end

function love.keyreleased(key)
   if key == "w" then
    shoot(1)  love.audio.play (woosh)
   elseif key == "d" then
     shoot(3)  love.audio.play (woosh)
   elseif key == "a" then
     shoot(2)  love.audio.play (woosh)
   elseif key == "i" then
	 state = 3
   elseif key == "m" and state == 2 or state == 3 then
	 state = 0
	 pTimer = 0
	 drawMenu()
   end
end


function shoot(dir)
	
	local shot = {}
	shot.x = hero.x+hero.width/2
	shot.y = hero.y
    shot.dir = dir	
	table.insert(hero.shots, shot)
		
end


function CheckCollision(box1x, box1y, box1w, box1h, box2x, box2y, box2w, box2h)
    if box1x > box2x + box2w - 1 or -- Is box1 on the right side of box2?
       box1y > box2y + box2h - 1 or -- Is box1 under box2?
       box2x > box1x + box1w - 1 or -- Is box2 on the right side of box1?
       box2y > box1y + box1h - 1    -- Is b2 under b1?
    then
        return false                -- No collision. Yay!
    else
	
        return true                 -- Yes collision. Ouch!
    end
end
Sorry for my code being so messy :\

UPDATE:

So I figured out how to trigger the animation when the bullet hits the enemy, but now I can't figure out how to make the explosion trigger in the appropriate place.

I tried (in function drawGame):

Code: Select all

anim:draw (enemy.x, enemy.y)

But that only applies to the last enemy in the row. I need a way for all of the enemies to be included.
Thanks.

please help,
thanks.
Last edited by worldaway on Wed May 30, 2012 12:04 am, edited 3 times in total.

worldaway
Prole
Posts: 44
Joined: Thu Sep 08, 2011 2:22 am

Re: To Trigger Animations At Certain Times

Post by worldaway » Sun May 27, 2012 11:15 pm

bump, please help guys.

User avatar
Puzzlem00n
Party member
Posts: 171
Joined: Fri Apr 06, 2012 8:49 pm
Contact:

Re: To Trigger Animations At Certain Times

Post by Puzzlem00n » Mon May 28, 2012 12:47 am

Well, I don't have time to fully answer your question, but seeing that you're desperate for an answer, I'll give you some of my ideas. I think you should somehow put all the explosions x and y (from vv.x and vv.y) in a table and draw them on the screen from that. A problem with that, though, is that you'd need different instances of the explosion animation, which I'm not even sure Lua can do without some workarounds (I think instances are only an OOP thing.)
Also, as a tip to condense the code, I think you should probably somehow make the enemies and fastEnemies the same thing, except with a speed parameter. That way, you don't have to copy-paste code for both all over the thing, like how you have two collision checking loops and two spawning loops.
I LÖVE, therefore I am.

worldaway
Prole
Posts: 44
Joined: Thu Sep 08, 2011 2:22 am

Re: To Trigger Animations At Certain Times

Post by worldaway » Mon May 28, 2012 5:43 am

So I figured out how to trigger the animation when the bullet hits the enemy, but now I can't figure out how to make the explosion trigger in the appropriate place.

I tried (in function drawGame):

Code: Select all

anim:draw (enemy.x, enemy.y)
But that only applies to the last enemy in the row. I need a way for all of the enemies to be included.
Thanks.

User avatar
Puzzlem00n
Party member
Posts: 171
Joined: Fri Apr 06, 2012 8:49 pm
Contact:

Re: To Trigger Animations At Certain Times - help?

Post by Puzzlem00n » Wed May 30, 2012 12:21 am

Maybe something like:

Code: Select all

for q,r in ipairs(enemies) do
  anim:draw(r.x, r.y)
end
Or of that nature? I still can barely follow all your code. You may need to change it for whatever property the ones just shot have.
I LÖVE, therefore I am.

worldaway
Prole
Posts: 44
Joined: Thu Sep 08, 2011 2:22 am

Re: To Trigger Animations At Certain Times - help?

Post by worldaway » Wed May 30, 2012 12:45 am

Puzzlem00n wrote:Maybe something like:

Code: Select all

for q,r in ipairs(enemies) do
  anim:draw(r.x, r.y)
end
Or of that nature? I still can barely follow all your code. You may need to change it for whatever property the ones just shot have.
Yah, I was thinking of that kind of thing, but It wouldn't work. I used

Code: Select all

for i,v in ipairs (enemies) do
		anim:draw (v.x, v.y)
end
Didn't give me an error, just nothing happens.

Yeah my code is super messy, but this game is almost done so I just want to finish it, and hopefully be more organized on my next project.

User avatar
Roland_Yonaba
Inner party member
Posts: 1563
Joined: Tue Jun 21, 2011 6:08 pm
Location: Ouagadougou (Burkina Faso)
Contact:

Re: To Trigger Animations At Certain Times - help?

Post by Roland_Yonaba » Wed May 30, 2012 10:35 am

I didn't tried, but it might work...Create different animations for each ennemies.
No, that won't be really costly, cause internally, AnAl stores for each animation, a single reference to an image already loaded once in memory, and a set of quads. Basically, if your ennemies share the same tileset, I guess, just load it once, then store a new animation inside each ennemy table:

Code: Select all

local tileset = love.graphics.newImage(...)
local N_ENNEMY = ... --the very number of ennemies needed
local ennemies = {}
   for i=1,N_ENNEMY do 
   ennemies[i] = {}
   -- .. defines ennemies properties
   ennemies[i].animOnCollision = newAnimation(...)
   ennemies[i].animOnCollision:setMode("once")
   end
Then trigging these animations shouldn't be hard:

Code: Select all

for i,ennemy in ipairs(ennemies) do
   if CheckCollision(ennemy,bullet) then
   --Mark him for later removal
   ennemy:animOnCollision:draw(ennemy.x,ennemy.y)
   end
end
As I said, untested, but might work.I never used AnAL but, as the code is cleary written and very straightforward to figure out, I have a general idea on how it works.

User avatar
tsturzl
Party member
Posts: 161
Joined: Fri Apr 08, 2011 3:24 am

Re: To Trigger Animations At Certain Times - help?

Post by tsturzl » Wed May 30, 2012 3:46 pm

You're code is objective, but in a seemingly weird way... Your objects should have there own methods so inside each object is the code to control that object. Usually I give objects there own init(load), update, and draw functions. This organizes your code and later on can prevent a mess of oddly named variables in the same scope.

Bullets could just be rectangles that are collidible. You should have an enemy object, in that object you should have an AnAL object for your base animation of your enemy. Upon destruction of the enemy simply replace the AnAL object with another AnAL object(possibly reuse the object) that represents the explosion animation, which respectively uses your objects x and y coordinates, thus spawning in the same place. You should then remove the enemy object after the animation time has elapsed. This is a simple calculation, animation speed * frames=animation time.

You should also have an object for your player, where you keep a table of the bullets. You may want to even make an object for the bullets, so you dont put bullet code inside of your player object.

Let me just say this. If you're going to code objectively, code objectively. If you're going to code procedurally, code procedurally. Don't mix styles, it makes a mess.

coke905
Citizen
Posts: 52
Joined: Tue Jun 05, 2012 1:46 am

Re: To Trigger Animations At Certain Times - help?

Post by coke905 » Tue Jun 05, 2012 5:13 am

K honestly I'm just starting love and I find c++ and allegro incredibly easy. I'm able to create an animation within 5 minutes in c ++ and allegro. But now I see all these people asking for help including me. I like love and I'm planning on sticking with it. Anyone know how I cud do basic character animation. It's one sheet and sprites are 32 x 32. I heard quads can do it so quad tutorial wud be extremely nice thanks ;)

User avatar
Roland_Yonaba
Inner party member
Posts: 1563
Joined: Tue Jun 21, 2011 6:08 pm
Location: Ouagadougou (Burkina Faso)
Contact:

Re: To Trigger Animations At Certain Times - help?

Post by Roland_Yonaba » Tue Jun 05, 2012 9:13 am

coke905 wrote:I heard quads can do it so quad tutorial wud be extremely nice thanks ;)
Found on the Wiki.
And more about Quads here and here, too.

Post Reply

Who is online

Users browsing this forum: No registered users and 6 guests