Making a Bullet Hell

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.
haazet
Prole
Posts: 8
Joined: Fri Jan 01, 2016 12:45 pm

Making a Bullet Hell

Post by haazet »

Hey everyone, im new to coding but have messed around with Lua on the PSP a long time ago and managed a Tetris game.Im working on a 3DS now. And have my game running for the most part but needs the enemies to spawn a bullet pattern.
Image

Im trying to make a Ikaruga clone and could use some pointers regarding bullet engines for enemy shots (like BulletLOVE was a great start it seems) but looking at its source it seems the game logic is stored in a .txt file im unfamilar with not a .lua. And was hoping there was a simplier way or example I can see of enemy shooting. That sprays out some small square .pngs from the enemy.x and enemy.y or something simple like that

BulletLOVE
https://www.love2d.org/forums/viewtopic ... 5&p=110105

LDME - Love Danmaku Maker Framework
viewtopic.php?f=5&t=80561&p=186723&hili ... ll#p186723

This is super inpressive bullet pattern for Lua, but I think far beyond me (Scroll down for gif on pattern)
https://github.com/sanford1/BulletLua
Image

Ive been looking around on google a lot but just cannot get a concept of this. Could some one shed some light in simpler terms or a example pulled from one
.
Sorry for a such simple question, having trouble making the enemy's shot anything. I can shot and destroy enemy's no problem, and the can kill me. Also have a point system. I use the 3ds rotated like a book and the touchscreen as movement, and you can only shoot backwards which I thought is kind of unusual idea for points
Last edited by haazet on Wed Jan 06, 2016 7:28 am, edited 3 times in total.
User avatar
zorg
Party member
Posts: 3444
Joined: Thu Dec 13, 2012 2:55 pm
Location: Absurdistan, Hungary
Contact:

Re: Making a Bullet Hell

Post by zorg »

Hi there!

Besides me being a tiny bit biased thanks to looking into how danmakufu works, i think i can try explain a few things. :3
Or at least, ramble a bit hoping some stuff will help you out

The easier questions relate to how advanced you want your bullet scripts to be;
  • With just one shot, you of course would have the usual members like position in coordinates, velocity either in a vector (that is, angle and speed components, or in polar coordinates) or just the dx,dy values (as in, cartesian coordinates) for the change in position per-coordinates (or even both).
  • A bit more would be to have acceleration as well (again, either with a vector, or deltas or both)
  • Another thing would be the angle the sprite is "facing", regardless of the heading (i like to implement this as a vector too, since the i can have an angular velocity that manipulates it, but this can be a simple number too)
  • How these change over time is what controls a bullet; could be a given script internal to the bullet itself, or an "external" pattern script; both just overwrite some data like the velocity vector on some defined frames.
The hard part comes when you want more than one bullet.
  • I'd personally have a parent member of each bullet, and assign another bullet (or an enemy) to it.
  • The question of whether the children should move relatively to a parent, or absolutely.
  • More specialized stuff, like getting the angle to the player, or adding some (seeded!) pseudo-randomness to the aiming or to the speed of the bullets.
  • Bias ahoy; danmakufu (the old version; new one is more about event handling) actually uses things similar to lua's coroutines for better structuring the code, since one can separate concerns like updating the character and a potential boss character (and its bullet patterns) per-frame with yielding from a coroutine instead of needing if-else chains for each frame number... see the example below.
  • Didn't want to include this, but if you wanted to include reversing mechanics (or just a reversible replay system, non-reversible is easier), you'd have to go the hard route and compute and store the state of everything per-frame, since we'd need to know where everything was at every frame.
Finally, the eye candy part. (Wanted to include it, sorry ^^)
  • Should the bullets be animated? use a sprite atlas, and progress through it with quads; use a spritebatch, it makes things faster! ;)
  • Maybe use shaders when drawing, for effects like rainbow bullets or other stuff.
Last but not least, some pseudocode:

Code: Select all

-- Note: when you see frame, i'm actually talking about ticks, or the update rate; how fast one renders to the screen would be the framerate, and it should be separated from the update speed for various reasons, but ultimately for consistent gameplay; the default love.run game loop doesn't separate them, caveat emptor.

-- Just a simple function
function boss:update(frame) -- not dt, we want to be deterministic!
	--start the boss at the top of the playfield
	if frame == 1 then
		self.position.x, self.position.y = playfield.width / 2, 0
	end
	-- every 5*60th frame (or five seconds) shoot a bullet pattern
	-- could be done a dozen other ways too, like patterns not being in the boss char itself, but this will do
	if frame % 60 == 0 then
		self:shoot(self.bullet)
	end
end

-- Now, for the pattern
bullet = {
	-- position
	x = 0,
	y = 0,
	-- velocity
	r = 1, -- magnitude
	a = 0, -- angle
	-- inheritance
	--parent   -- the boss id set at spawn, or other bullet ids depending on behaviour
	--chilren  -- other bullets or even enemies, bullets firing bullets!
}

bullet:update(frame)
	-- for each frame, calculate the next position using the velocity vector
	local dx, dy = self.r * math.cos(self.a), self.r * math.sin(self.a)
	self.x, self.y = self.x + dx, self.y + dy
	-- now, you can either make such bullet scripts by having a bigger pattern object, that creates things with methods
	-- (in which case, you needn't do anything else here)
	-- or you could have each bullet have a script... a function inside them
	self.script:update(frame)
	-- that would create other bullets and set their parent to this bullet
end
Me and my stuff :3True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.
haazet
Prole
Posts: 8
Joined: Fri Jan 01, 2016 12:45 pm

Re: Making a Bullet Hell

Post by haazet »

Thanks for the help! Im gonna have to pour over that awhile with some more learning. And hopefully get some sort of pattern out of a enemy eventually

Heres my code if anyone wondering, Not much now just a lot of basic tutorial level stuff and some 3DS implemented features

Code: Select all

--playerImg = nil -- this is just for storage used to be this { x = 10, y = 120, speed = 100, img = nil }
player = {}
player.x = 10
player.y = 120
player.speed = 10 

-- Enables 3D mode.
	love.graphics.set3D(true)

--Bullet Stuff
-- Timers
-- We declare these here so we don't have to edit them multiple places
canShoot = true
canShootTimerMax = 0.2 
canShootTimer = canShootTimerMax

-- Image Storage
bulletImg = nil

-- Entity Storage
bullets = {} -- array of current bullets being drawn and updated


--Enemy Stuff--------
--More timers
createEnemyTimerMax = 0.4
createEnemyTimer = createEnemyTimerMax
  
-- More images
enemyImg = nil -- Like other images we'll pull this in during out love.load function
  
-- More storage
enemies = {} -- array of current enemies on screen


-- Collision detection taken function from http://love2d.org/wiki/BoundingBox.lua
-- Returns true if two boxes overlap, false if they don't
-- x1,y1 are the left-top coords of the first box, while w1,h1 are its width and height
-- x2,y2,w2 & h2 are the same, but for the second box
function CheckCollision(x1,y1,w1,h1, x2,y2,w2,h2)
  return x1 < x2+w2 and
         x2 < x1+w1 and
         y1 < y2+h2 and
         y2 < y1+h1
end
isAlive = true
score = 0

--MOUSE STUFF
function player.move_to(_x, _y)
   dx = _x - player.x
   dy = _y - player.y
   length = math.sqrt(dx*dx+dy*dy);

   dx = (dx/length)
   dy = (dy/length)

   player.x = (player.x + dx * player.speed)
   player.y = (player.y + dy * player.speed)
   end


function love.load(arg)
love.graphics.setScreen('top')
player.img = love.graphics.newImage('plane.png')
redplayer = love.graphics.newImage('redplayer.png')
leftred = love.graphics.newImage('redleft.png')
blueplayer = love.graphics.newImage('plane.png')
leftblue = love.graphics.newImage('leftblue.png')
rightblue = love.graphics.newImage('rightblue.png')
background = love.graphics.newImage('background.png')
bottombg = love.graphics.newImage('bottombg.png')
won = love.graphics.newImage('won.png')
    
	
	bulletImg = love.graphics.newImage('bullet.png')
	enemyImg = love.graphics.newImage('enemy.png')
end




-- Updating
function love.update(dt)

-- Time out how far apart our shots can be. PLayer Shots
canShootTimer = canShootTimer - (1 * dt)
if canShootTimer < 0 then
  canShoot = true
end
	
	
	-- PLayer Shooting
	if love.keyboard.isDown('cpaddown') and canShoot then
	-- Create some bullets
	newBullet = { y = player.y + (player.img:getWidth()/2), x = player.x + 50, img = bulletImg }
	table.insert(bullets, newBullet)
	canShoot = false
	canShootTimer = canShootTimerMax
end
-- update the positions of bullets
for i, bullet in ipairs(bullets) do
	bullet.x = bullet.x - (350 * dt)

  	if bullet.y < 0 then -- remove bullets when they pass off the screen
		table.remove(bullets, i)
	end
end

-- Time out enemy creation
createEnemyTimer = createEnemyTimer - (1 * dt)
if createEnemyTimer < 0 then
	createEnemyTimer = createEnemyTimerMax

	-- Create an enemy
	randomNumber = math.random(10, love.graphics.getWidth() - 10)
	newEnemy = { x = 410, y = randomNumber, img = enemyImg }
	table.insert(enemies, newEnemy)
end
-- update the positions of enemies
for i, enemy in ipairs(enemies) do
	enemy.x = enemy.x - (200 * dt)

	if enemy.x > 850 then -- remove enemies when they pass off the screen
		table.remove(enemies, i)
	end
end

-- run our collision detection
-- Since there will be fewer enemies on screen than bullets we'll loop them first
-- Also, we need to see if the enemies hit our player
for i, enemy in ipairs(enemies) do
	for j, bullet in ipairs(bullets) do
		if CheckCollision(enemy.x, enemy.y, enemy.img:getWidth(), enemy.img:getHeight(), bullet.x, bullet.y, bullet.img:getWidth(), bullet.img:getHeight()) then
			table.remove(bullets, j)
			table.remove(enemies, i)
			score = score + 1
		end
	end

	if CheckCollision(enemy.x, enemy.y, enemy.img:getWidth(), enemy.img:getHeight(), player.x, player.y, player.img:getWidth(), player.img:getHeight()) 
	and isAlive then
		table.remove(enemies, i)
		isAlive = false
	end
end

--Restarting after death
if not isAlive and love.keyboard.isDown('up') then
	-- remove all our bullets and enemies from screen
	bullets = {}
	enemies = {}

	-- reset timers
	canShootTimer = canShootTimerMax
	createEnemyTimer = createEnemyTimerMax

	-- move player back to default position
	player.x = 10
	player.y = 120

	-- reset our game state
	score = 0
	isAlive = true
end

--Input
if love.keyboard.isDown('left') then
	if player.y > 0 then -- binds us to the map
		player.y = player.y - (player.speed*dt)
		player.img = leftblue
	end
elseif love.keyboard.isDown('right') then
	if player.y < 140  then
		player.y = player.y + (player.speed*dt)
		player.img = rightblue
	end
end
-- Vertical movement
if love.keyboard.isDown('up') then
	if player.x > 0 then
		player.x = player.x - (player.speed*dt)
	end
elseif love.keyboard.isDown('down') then
	if player.x < 410 then
		player.x = player.x + (player.speed*dt)
		player.img = blueplayer
	end
end

--Colors Swicth of player RED BLUE
if love.keyboard.isDown('cpadright') then
player.img = redplayer
elseif love.keyboard.isDown('cpadleft') then
player.img = blueplayer
end







end





function love.draw(dt)
love.graphics.setScreen('bottom')
love.graphics.draw(bottombg, 0, 0)
love.graphics.setScreen('top')
love.graphics.draw(background, 0, 0)

if isAlive then
love.graphics.draw(player.img, player.x, player.y)
else
	love.graphics.print("Press 'Dpad Up' to restart", love.graphics:getWidth()/2-50, love.graphics:getHeight()/2-10)
end

for i, bullet in ipairs(bullets) do
  love.graphics.draw(bullet.img, bullet.x, bullet.y)
end
--Enemies Draw
for i, enemy in ipairs(enemies) do
	love.graphics.draw(enemy.img, enemy.x, enemy.y)
end
--Score Display
love.graphics.setColor(255, 255, 255)
love.graphics.print("SCORE: " .. tostring(score), 250, 5)

--Still Updating MOuse MOvement
if love.mouse.isDown('l') then --Check every frame if left mouse button is down
   local mousex, mousey = love.mouse.getPosition() --Get mousex and mousey because it's not given to us
   player.move_to(mousex, mousey)
end

--You won
if score > 10 then
--love.graphics.set3D(true)
--love.graphics.setDepth(1)
love.graphics.draw(won, 0, 0)
--love.graphics.setDepth(3)
love.graphics.draw(blueplayer, 200, 120)
--love.graphics.set3D(false)
isAlive = false
end





end

Edit: I managed to get the enemys shooting straight and have there own collision) Now onto the math
haazet
Prole
Posts: 8
Joined: Fri Jan 01, 2016 12:45 pm

Re: Making a Bullet Hell

Post by haazet »

If anyone has the time to take a quick look at this to point out the obvious much appreciated.

Ive gotten a bit farther and have enemies shooting multiple bullets in a straight line along the x and a nice scrolling background. Id like to have a second set of enemies almost the same coming from the y, but with its own set of collision so I can have them only collide with the correct color of player (Red/Blue) and give the game some tactics.

So I copied all the stuff from the enemies and enemiebullet tables with its own timers and such and renamed Red infront of them Redenenemybullet/enemybullet etc. But i was getting a bunch of errors that im calling a nil global value. Now my new enemies are scrolling down fine but my original enemies are gone and when it trys to spawn them throws a errors" Global variable enemy is not found" even though they were working previously

I think it has to do with how im closing the arguments like
"for i, RedenemyBullet in ipairs(RedenemyBullets) do"

or am I just going about this all wrong

Code: Select all

 debug = true
--Player Table
Player = { x = 20, y = 120, speed = 10, sprite = nil, HP = 10}
isAlive =  false
score = 0
--
------
if Player.HP == 0 then
	isAlive = false
end

--Scrolling
	windowx = love.graphics.getWidth()
	
	bg1 = {}
	bg1.img = love.graphics.newImage("back1.png")
	bg1.x = 0
	bg1.width = bg1.img:getWidth()


	
	speed = 30
	
--MOUSE STUFF
function Player.move_to(_x, _y)
   dx = _x - Player.x
   dy = _y - Player.y
   length = math.sqrt(dx*dx+dy*dy);

   dx = (dx/length)
   dy = (dy/length)

   Player.x = (Player.x + dx * Player.speed)
   Player.y = (Player.y + dy * Player.speed)
   end
------
----Bullet Stuff
-- Timers
-- We declare these here so we don't have to edit them multiple places
canShoot = true
canShootTimerMax = 0.1
canShootTimer = canShootTimerMax
---- Image Storage
bulletSprite = nil
--Red Bullet

-- Entity Storage
bullets = {}
--Red Entity Storage
 
----Enemy Stuff--------
--More timers
createEnemyTimerMax = .5
createEnemyTimer = createEnemyTimerMax
--Red Enemy timer
createRedEnemyTimerMax = .5
createRedEnemyTimer = createRedEnemyTimerMax
-- More storage
enemies = {}-- array of current enemies on screen
--Red Enemies
Redenemies = {} 
-- More images
enemySprite = nil
--2nd enemy!!
RedenemySprite =nil 
---Regular enemy shot
enemyBulletSprite = nil
enemyBullets = {}

canShootEnemy = true
canShootEnemyTimerMax = 0.3
canShootEnemyTimer = canShootEnemyTimerMax
--2nd enemy shot
RedenemyBulletSprite = nil
RedenemyBullets = {}
--RedcanShoot
RedcanShootEnemy = true
RedcanShootEnemyTimerMax = 0.3
RedcanShootEnemyTimer = RedcanShootEnemyTimerMax
--
function love.load(arg)
--Lets draw to the Top Screen
love.graphics.setScreen('top')
--
Player.sprite = love.graphics.newImage('Plane.png')
enemyBulletSprite = love.graphics.newImage('EnemyBullet.png')
bulletSprite = love.graphics.newImage('Bullet.png')
enemySprite = love.graphics.newImage('Enemy.png')
Background = love.graphics.newImage('Background.png')
BottomBG = love.graphics.newImage('bottombg.png')
WonTop = love.graphics.newImage('WonTop.png')
WonBottom = love.graphics.newImage('WonBottom.png')

--2nd enemy 
RedenemySprite =  love.graphics.newImage('Enemy.png')
RedenemyBulletSprite = love.graphics.newImage('Bullet.png')

end

--




function love.draw(dt)----------------------------
--

love.graphics.setScreen('bottom')
love.graphics.draw(BottomBG, 0, 0)
love.graphics.setScreen('top')
love.graphics.draw(Background, 0, 0)
love.graphics.draw(bg1.img, bg1.x, 0)


--Starting Menu	
	
if Player.HP == 0 then
	isAlive = false
end

	
	
   if isAlive then
	for i, enemyBullet in ipairs(enemyBullets) do
		love.graphics.draw(enemyBullet.sprite, enemyBullet.x, enemyBullet.y)
	end
	--
	--
	love.graphics.draw(Player.sprite, Player.x, Player.y)
	--
	for i, bullet in ipairs(bullets) do
		love.graphics.draw(bullet.sprite, bullet.x, bullet.y)
	end
	--
	for i, enemy in ipairs(enemies) do
		love.graphics.draw(enemy.sprite, enemy.x, enemy.y)
	end
	
	-- 2nd Enemy
	for i, RedenemyBullet in ipairs(RedenemyBullets) do
		love.graphics.draw(RedenemyBullet.sprite, RedenemyBullet.x, RedenemyBullet.y)
	end
	
	for i, Redenemy in ipairs(Redenemies) do
		love.graphics.draw(Redenemy.sprite, Redenemy.x, Redenemy.y)
	end
	--
	
	love.graphics.print("Score: " .. score, love.graphics:getWidth()-80, 15)
	love.graphics.print("Lives: " .. Player.HP, 10, 15)
else
	love.graphics.print("You Have Lost", love.graphics:getWidth()/2-50, love.graphics:getHeight()/2-10)
	love.graphics.print("Your score is: " .. score, love.graphics:getWidth()/2-50, love.graphics:getHeight()/2-30)
	love.graphics.setScreen('bottom')
love.graphics.draw(WonBottom, 0, 0)
end
----Still Updating MOuse MOvement
if love.mouse.isDown('l') then --Check every frame if left mouse button is down
   local mousex, mousey = love.mouse.getPosition() --Get mousex and mousey because it's not given to us
   Player.move_to(mousex, mousey)
end



 



end


--

function love.update(dt)
--BG SCROLLINg
bg1.x = bg1.x - speed * dt
	

	if bg1.x < 0 then
		bg1.x = bg1.x + 0
	end
	
-- Time out enemy creation
	createEnemyTimer = createEnemyTimer - (1*dt)
	if createEnemyTimer < 0 then
		createEnemyTimer = createEnemyTimerMax
			-- Create an enemy
		rand = math.random(10, love.graphics.getHeight() - 10 )
		newEnemy = { x = 410, y = rand, sprite = enemySprite }
    newEnemy.canShoot = true
    newEnemy.timer = 0
		table.insert(enemies, newEnemy)
	end
		-- 2nd enemy timer
		createRedEnemyTimer = createRedEnemyTimer - (1*dt)
	if createRedEnemyTimer < 0 then
		createRedEnemyTimer = createRedEnemyTimerMax
--2nd enemy creation
-- Create an enemy
		rand = math.random(10, love.graphics.getHeight() - 10 )
		newRedEnemy = { x = rand, y = -10, sprite = RedenemySprite }
    newRedEnemy.canShoot = true
    newRedEnemy.timer = 0
		table.insert(Redenemies, newRedEnemy)
	end
	
if Player.HP == 0 then
	isAlive = false
end
if isAlive == true then

--Check Shooting
	for i, enemy in ipairs(enemies) do
    
   -- Update Shooting interval timer ---
    enemy.timer = enemy.timer - (1*dt)
    if enemy.timer < 0 then
      enemy.canShoot = true
    end
	end
	-- Spawn Bullet --
	for i, enemy in ipairs(enemies) do
		if enemy.canShoot then
			newEnemyBullet = { x = enemy.x + enemy.sprite:getWidth()/2 - enemyBulletSprite:getWidth()/2, y = enemy.y + enemy.sprite:getHeight() - enemyBulletSprite:getHeight(), sprite = enemyBulletSprite}
			table.insert(enemyBullets, newEnemyBullet)
			enemy.canShoot = false
      enemy.timer = canShootEnemyTimerMax
		end
	end
	
		--2nd enemy updat timer
	for i, Redenemy in ipairs(Redenemies) do
	Redenemy.timer = Redenemy.timer - (1*dt)
    if Redenemy.timer < 0 then
      Redenemy.canShoot = true
    end
	end
	
	--2nd enemy spawn bullet
	for i, Redenemy in ipairs(Redenemies) do
	if Redenemy.canShoot then
			newRedEnemyBullet = { x = Redenemy.x + Redenemy.sprite:getWidth()/2 - RedenemyBulletSprite:getWidth()/2, y = Redenemy.y + Redenemy.sprite:getHeight() - RedenemyBulletSprite:getHeight(), sprite = RedenemyBulletSprite}
			table.insert(RedenemyBullets, RednewEnemyBullet)
			Redenemy.canShoot = false
      Redenemy.timer = canShootEnemyTimerMax
		end
		end
	
    -- Check for Collisions ---- run our collision detection
		for j, bullet in ipairs(bullets) do
			if enemy.HP == nil then
				enemy.HP = 2
			end
			if CheckCollision(enemy.x, enemy.y, enemy.sprite:getWidth(), enemy.sprite:getHeight(), bullet.x, bullet.y, bullet.sprite:getWidth(), bullet.sprite:getHeight()) then
				enemy.HP = enemy.HP - 1
				table.remove(bullets, j)
				if enemy.HP == 0 then
					table.remove(enemies, i)
					score = score + 10
					enemy.HP = 2
				end
			end
		end
    
--Shooting enemies-- run our collision detection
		for k, enemyBullet in ipairs(enemyBullets) do
			if CheckCollision(enemyBullet.x, enemyBullet.y, enemyBullet.sprite:getWidth(), enemyBullet.sprite:getHeight(), Player.x, Player.y, Player.sprite:getWidth(), Player.sprite:getHeight())
				and isAlive then
					Player.HP = Player.HP - 1
					table.remove(enemyBullets, k)
			end
		end
		for k, enemyBullet in ipairs(enemyBullets) do
		if CheckCollision(enemy.x, enemy.y, enemy.sprite:getWidth(), enemy.sprite:getHeight(), Player.x, Player.y, Player.sprite:getWidth(), Player.sprite:getHeight())
			and isAlive then
				Player.HP = Player.HP - 1
				table.remove(enemies, i)
		end
	end
	
--Shooting-- Player Shots Time out how far apart our shots can be. PLayer Shots?
	canShootTimer = canShootTimer - (1*dt)
	if canShootTimer < 0 then
		canShoot = true
	end
	
	-- PLayer Shooting
	if love.keyboard.isDown('cpaddown') and canShoot then
	-- Create some bullets
		newBullet = { x = Player.x + (Player.sprite:getWidth()/2) - (bulletSprite:getWidth()/2), y = Player.y, sprite = bulletSprite}
		table.insert(bullets, newBullet)
		canShoot = false
		canShootTimer = canShootTimerMax
	end
--Bullets move-- update the positions of bullets
	for i, bullet in ipairs(bullets) do
		bullet.x = bullet.x - (350 * dt)
		if bullet.y < 0 then -- remove bullets when they pass off the screen
			table.remove(bullets, i)
		end
	end
--Enemy bullets move
	for i, enemyBullet in ipairs(enemyBullets) do
		enemyBullet.x = enemyBullet.x - (350 * dt)
		if enemyBullet.x < 0 then
			table.remove(enemyBullets, i)
		end
	end
	--2nd enemy bullets move
	for i, RedenemyBullet in ipairs(RedenemyBullets) do
		RedenemyBullet.y = RedenemyBullet.y + (350 * dt)
		if RedenemyBullet.x < 0 then
			table.remove(RedenemyBullets, i)
		end
	end
--Enemies move-- update the positions of enemies
	for i, enemy in ipairs(enemies) do
		enemy.x = enemy.x - (200*dt)

		if enemy.x < 0  then
			table.remove(enemies, i)
			if score > 0 then
				score = score - 50
				
			
			end
		end
	end
	--2nd enemies move
	for i, Redenemy in ipairs(Redenemies) do
		Redenemy.y = Redenemy.y + (200*dt)

		if Redenemy.x < 0  then
			table.remove(Redenemies, i)
			if score > 0 then
				score = score - 50
				
			
			end
		end
	end
--Moving
	if love.keyboard.isDown('left') then
		if Player.x > 0 then
			Player.x = Player.x - (Player.speed*dt)
		end
	elseif love.keyboard.isDown('right') then
		if Player.x < (love.graphics.getWidth() - Player.sprite:getWidth()) then
			Player.x = Player.x + (Player.speed*dt)
		end
	end

	if love.keyboard.isDown('up') then
		if Player.y > 0 then
			Player.y = Player.y - (Player.speed*dt)
		end
	end

	if love.keyboard.isDown('down') then
		if Player.y < (love.graphics.getHeight() - Player.sprite:getHeight()) then
			Player.y = Player.y + (Player.speed*dt)
		end
	end
--When u dead
else
--Restarting after death
	if love.keyboard.isDown('a') then
		bullets = {}
		enemyBullets = {}
		RedenemyBullets = {}
		enemies = {}
		Redenemies = {}
		canShootTimer = canShootTimerMax
		RedcanShootTimer = RedShootTimerMax
		createEnemyTimer = createEnemyTimerMax
		createRedEnemyTimer = createRedEnemyTimerMax
		score = 0
		isAlive = true
		Player.HP = 5
		Player.x = 40
		Player.y = 120
	end
enda
end
-- Escape


-- Collision detection taken function from http://love2d.org/wiki/BoundingBox.lua
-- Returns true if two boxes overlap, false if they don't
-- x1,y1 are the left-top coords of the first box, while w1,h1 are its width and height
-- x2,y2,w2 & h2 are the same, but for the second box
function CheckCollision(x1,y1,w1,h1, x2,y2,w2,h2)
	return x1 < x2+w2 and
		   x2 < x1+w1 and
		   y1 < y2+h2 and
		   y2 < y1+h1
end




   
Last edited by haazet on Mon Jan 04, 2016 2:11 am, edited 1 time in total.
User avatar
zorg
Party member
Posts: 3444
Joined: Thu Dec 13, 2012 2:55 pm
Location: Absurdistan, Hungary
Contact:

Re: Making a Bullet Hell

Post by zorg »

A few things;

Code: Select all

RedcanShootEnemyTimer = canShootEnemyTimerMax -- You probably wanted RedcanShootEnemyTimerMax there, though currently, both values are the same.

Code: Select all

love.graphics.setScreen('top') -- apart from this not being a method löve gives... did you load TLfres or something into the love.graphics table?
Also, it might help with debugging if you posted the full error message, so we know where/which line and function the error originated from
Me and my stuff :3True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.
User avatar
Nixola
Inner party member
Posts: 1949
Joined: Tue Dec 06, 2011 7:11 pm
Location: Italy

Re: Making a Bullet Hell

Post by Nixola »

The latter is a function in a 3DS port of LÖVE, if I recall correctly
lf = love.filesystem
ls = love.sound
la = love.audio
lp = love.physics
lt = love.thread
li = love.image
lg = love.graphics
haazet
Prole
Posts: 8
Joined: Fri Jan 01, 2016 12:45 pm

Re: Making a Bullet Hell

Post by haazet »

Thanks for noticing the RedcanShootEnemyTimer = canShootEnemyTimerMax. It was causing a lot of fps slow down. I still drawing only the new enemys now, and after a second or 2 it throws a error about the index global enemy being nil.(the original ones I want back)

Here is the Error
https://love2d.org/imgmirrur/hYQcx.html

Perhaps my restart after death function I use at the very start since alive = false needs to add ReddcanShooEnemyTimer and create the red timer?

Code: Select all

--Restarting after death
	if love.keyboard.isDown('a') then
		bullets = {}
		enemyBullets = {}
		enemies = {}
		canShootTimer = canShootTimerMax
		createEnemyTimer = createEnemyTimerMax
		score = 0
		isAlive = true
		Player.HP = 5
		Player.x = 40
		Player.y = 120
	end
end
Im a bit lost why its spawning the new enemies at all yet

Edit: There some 3DS functions is use like love.graphics.set3D(true), love.graphics.setScreen('top')
Last edited by haazet on Mon Jan 04, 2016 2:20 am, edited 1 time in total.
User avatar
s-ol
Party member
Posts: 1077
Joined: Mon Sep 15, 2014 7:41 pm
Location: Cologne, Germany
Contact:

Re: Making a Bullet Hell

Post by s-ol »

haazet wrote:Thanks for noticing the RedcanShootEnemyTimer = canShootEnemyTimerMax. It was causing a lot of fps slow down. I still drawing only the new enemys now, and after a second or 2 it throws a error about the index global enemy being nil.(the original ones I want back)

Here is the Error
http://imgur.com/a/hYQcx

Perhaps my restart after death function I use at the very start since alive = false needs to add ReddcanShooEnemyTimer and create the red timer?

Code: Select all

--Restarting after death
	if love.keyboard.isDown('a') then
		bullets = {}
		enemyBullets = {}
		enemies = {}
		canShootTimer = canShootTimerMax
		createEnemyTimer = createEnemyTimerMax
		score = 0
		isAlive = true
		Player.HP = 5
		Player.x = 40
		Player.y = 120
	end
end
Im a bit lost why its spawning the new enemies at all yet

Edit: Here are the 3ds functions if your curious, having no problem here
https://github.com/VideahGams/LovePotio ... emented.md
The variable "enemy" isn't defined (= therefore assumed global and nil) and you're trying to access it. Your code snippets are the wrong spot, the error is giving you the right line to look at.

s-ol.nu /blog  -  p.s-ol.be /st8.lua  -  g.s-ol.be /gtglg /curcur

Code: Select all

print( type(love) )
if false then
  baby:hurt(me)
end
haazet
Prole
Posts: 8
Joined: Fri Jan 01, 2016 12:45 pm

Re: Making a Bullet Hell

Post by haazet »

Thanks, Ive been staring at the line 274 for awhile now. And just not grasping what happened, that area is untouched from when I had the original enemies come from the x and shooting and it worked perfect. Where have I misplaced it? I updated the code in post #4 its pretty much the same but the fix RedcanShootTimer and added this

Code: Select all

--Restarting after death
	if love.keyboard.isDown('a') then
		bullets = {}
		enemyBullets = {}
		RedenemyBullets = {}
		enemies = {}
		Redenemies = {}
		canShootTimer = canShootTimerMax
		RedcanShootTimer = RedShootTimerMax
		createEnemyTimer = createEnemyTimerMax
		createRedEnemyTimer = createRedEnemyTimerMax
		score = 0
		isAlive = true
		Player.HP = 5
		Player.x = 40
		Player.y = 120
	end
Edit: I kind of see i need (for i, enemy in ipairs(enemies) do) to define it so that got moved
User avatar
Beelz
Party member
Posts: 234
Joined: Thu Sep 24, 2015 1:05 pm
Location: New York, USA
Contact:

Re: Making a Bullet Hell

Post by Beelz »

You are resetting your tables every frame... Define once in load:

Code: Select all

bullets = {}
enemyBullets = {}
RedenemyBullets = {}
enemies = {}
Redenemies = {}
Then resetting after death just clear them with nil:

Code: Select all

if love.keyboard.isDown('a') then   -- This would also be better in the keypressed callback if pressing a is to reset the game...
  bullets = nil
  enemyBullets = nil
  RedenemyBullets = nil
  enemies = nil
  Redenemies = nil

  canShootTimer = canShootTimerMax
  RedcanShootTimer = RedShootTimerMax
  createEnemyTimer = createEnemyTimerMax
  createRedEnemyTimer = createRedEnemyTimerMax
  score = 0
  isAlive = true
  Player.HP = 5
  Player.x = 40
  Player.y = 120
end

Code: Select all

if self:hasBeer() then self:drink()
else self:getBeer() end
GitHub -- Website
Post Reply

Who is online

Users browsing this forum: Bing [Bot] and 33 guests