EUCLIOD - A Homebrew Bullet Hell for the 3DS

Before I say anything else, I'd like to mention that this project was developed and bugtested on, and for the New 3DS system.

Rinnegatamante has helped me optimize the game, and the game runs almost flawlessly on N3DS (at present) and although I am aiming to keep the game smooth as possible for the O3DS, don't expect any miracles. (Though I have been informed that the game currently runs at 60 FPS on the O3DS)

banner.png


This has been a quick project I've undertaken to have a little test of the boundaries of the N3DS's processing power vs the O3DS. (as seen through the eyes of Rinnegatamante's LPP)

It's also (hopefully) going to be the first game I actually complete in the last 7 years of making random games that are too ambitious for me to finish.

s3.png
s1.png
s9.png



s10.png
s5.png
s2.png



s7.png
s0.png
s8.png

Video by TCPixel (Thanks a tonne man)




I've only got three levels in at the moment (my level design skills suck) but the levels are stored in plain text file so it should be easy enough to create more. 6 enemies , 3 bosses with multiple phases, and 5 different weapons. It's a bullet hell game: so you get one life, and a tiny hitbox.

The difficulty system isn't tested, I did most of the bugtesting on the highest difficulty (for the sake of keeping an eye on lag levels), so I don't know if the easier ones are laughably easy or broken.

Controls:
A -
Select (menu only... I'm currently sick of holding down A when playing Mario Kart, and mashing it for Fantasy Life)
B - Back (only works on ship select screen)
Y - Fire Primary
R - Focus Mode (halve movement speed, and uses an alternate weapon)
Start - Return to Menu
Select - Take Screenshot
On the menu, use left and right to increase/decrease difficulty, and change the level (hold Y while changing level to speed-cycle)
You can remap the Fire and Focus controls to A, B, X, Y, L, R, ZL, or ZR in the options menu if you don't like the default.
The game is currently D-Pad only, but adding in circle pad controls wouldn't be a stretch. :)

If anyone gives a crap about level making:
The game will load from any level named correctly. levelx.dat should be the filename where x is the number with no spacers. The game will state invalid if the file does not exist or if the file does not have "v001" on the first line.
The game will likely crash if you have both these but the syntax in the file is incorrect.

Code:
v001 //add this to the start of every level you make, it won't start without it
|T-000100|en01|T|100
|T-000200|en02|L|050

Every line has to be exactly 20 characters long, in this exact format (my text-parser programming skills suck)
The first 6-digit number is the frame the enemy spawns, if you're not lagging this should be 60 per second.

The second cell is the enemy that's spawning.
  • "en01" (Fighter) is the enemy that targets you with bullets
  • "en02" (Bomber) is the enemy that sits still and shoots slow bullets directly downwards
  • "en03" (Strafer) is the sliding enemy that lays down a curtain
  • "en04" (Helix) is the enemy that shoots a helix of bullets and diagonal shots alternatively
  • "en05" (Kamikaze) is a slow moving enemy that proceeds down the screen and then detonates into a ring of bullets if not destroyed
  • "en06" (Asteroid) is a large object that soaks up player shots. Graphic and direction is deterministic based on the frame it was spawned in
  • "en07" (Odin) individual mob. Untested.
  • "bo01", "bo02" and "bo03" are the three current bosses, and spawn after a warning is flashed on screen. Note that two bosses cannot be spawned within a short period of eachother. (and probably not even on the same level, this is largely untested)
The third cell is what side of the screen the enemy will enter. Top, Left, or Right. Note that I haven't tested how en03 works when entering from the Top, and I haven't tested how bo01 works when entering from Left or Right. The whole enemy spawning system is really bare-bones at the moment.

The final cell is the coordinate the enemy spawns at. For Top spawning enemies, this number is the X-coordinate they spawn at, (between 0-400 for left-right) and for Left and Right spawning enemies, this is the Y coordinate. (0-240 for top-bottom)

Okay, bored now?

[3DSX] Release 6.1
  • Re-added a null file that had been accidentally removed, to fix the red bar loading issue
[CIA] Release 7
  • Bullets now clear on stage clear
  • Control configuration and theme does not currently save as the config file is in a read-only location
  • Sounds have been disabled as a crippling bug in CIA form causes sounds to loop and memory leak, I have not identified how to solve this problem
  • As the CIA is a compiled installation, there is not currently a way to use custom levels with the CIA version
[3DSX] Release 6
  • Added sound effects
  • Color scheme is now changeable from options menu. (includes high contrast black and white mode)
[3DSX] Release 5
  • Added new enemy, "Kamikaze"
  • Added new enemy, "Asteroid"
  • Enemies now will kill you on contact
  • Added Level 3, featuring the two new enemies and a new boss, "Odin's Fleet".
  • Bosses now clear bullets before starting the next phase
  • Corrected a calculation error with the scoring (Difficulty was linearly increasing score instead of multiplicatively)
  • Made some dramatic hitbox corrections for enemy ships
  • Increased Level 1 and 2 boss health by 140% to counter the hitbox change.
  • Grazing has temporarily been removed as a new, faster, and pixel-accurate player hit detection system has now been implemented. Grazing may be added back in a later update
  • Fixed a bug that was causing homebrew launched after EUCLIOD to have messed up graphics
  • FPS counter (hopefully should remain at 60 at all times)
  • Boss health bar
  • Debug mode (hold X before loading screen displays) includes "slideshow" recording which replaces screenshots, displays a couple debug values on the bottom screen, and ups Level 1's boss's final attack to one hundred and eleven for testing lag
  • Fixed a bug that was causing multiple level's enemies to load if you chose a level then backed out of the ship select screen before choosing another level
  • Credits added
  • Further improvements to overall system stability and other minor adjustments have been made to enhance the user experience
[3DSX] Release 4
  • Added variation to Level 2 boss's tidal wave attack to eliminate safespots
  • Added two ship types: "Tiger" and "Cicada"
  • Ship selection screen
  • The original ship, "Hawk", received a 25% movement speed reduction
  • Weapons are no longer freely scrollable. Each ship has a Primary weapon and a Focus weapon, which automatically engages when you enter focus mode. You can press Y on the ship selection screen to disable the focus weapon, which causes the Primary weapon to be used for both modes.
  • Corrected a bug that was preventing enemies from despawning and thus the level from being cleared
  • Increased graze range by 30% and doubled point reward for grazing
  • Taking screenshots now works
[3DSX] Release 3
  • Added level 2, including a new enemy (Helix "en04") and a new boss "bo02"
  • 3 New bullet types used by these two enemies: "Sway", "Diagonal", and "Moving Orbitals"
  • Corrected bug that was causing previously loaded level's enemies to spawn (only matters if anyone actually made any levels
  • Buffed seeker shot damage and tracking
  • Nerfed missile's hitbox
  • Exit button works now (big whoop)
  • Tweaked strafers so that they're not so insane on lower difficulties
  • Basic enemy shots now travel slower but have larger hitboxes
  • Basic score counter implemented. Kills and graze count towards score
  • The game will now return to menu once the level is cleared
  • Shortened enemy despawn time to reduce lag
  • Buffed boss health
  • Added "Stage Clear" text. Game will return to menu shortly afterwards

[3DSX] Release 2
  • Substantial optimization regarding boss bullet spawns, seeker rounds, all player shots in general, and moving enemies
  • N3DS mode automatically activates for N3DS systems. O3DS mode can still be forced by holding Y upon launch.
  • Combined, these two changes create a DRAMATIC performance boost for the game, so you can look forward to a lot more bullets in the future
  • The game now returns to menu several seconds after a death. You can still reset early by pressing Start.
  • Custom keybinds menu added. Keybind settings are persistent.
  • Enemies now despawn after 1000 ticks

3DSX: Just extract the archive straight to your SD card and launch via Homebrew Launcher. The unsuffixed zip files are the 3DSX versions.

CIA: Install the CIA using FBI. The zip file with "_CIA" on the end is the CIA version


Despite the CIA version having a more recent release, the 3DSX version is still superior. So if you don't mind going 3DSX over CIA, I'd recommend it.

Mod edit. Download links
https://gbatemp.net/attachments/eucliod_r6-zip.44049/
https://gbatemp.net/attachments/eucliod_r7_cia-zip.46345/
https://gbatemp.net/attachments/eucliod_r6-1-zip.64753/

Credit to Rinnegatamante for developing Lua Player Plus, the application that allows me to program in notepad and not need to know a single other thing about computers or compilers.
 

Attachments

  • Eucliod_r6.zip
    1.2 MB · Views: 1,043
  • Eucliod_r7_CIA.zip
    1.3 MB · Views: 949
  • Eucliod_r6.1.zip
    1.2 MB · Views: 622
Last edited by HexZyle,

HexZyle

Pretty Petty Pedant
OP
Member
Joined
Sep 12, 2015
Messages
300
Trophies
0
XP
452
Country
Australia
Quadtrees are a spatial sorting technique for quickly narrowing down potential collisions. By sorting things into "buckets" by position whenever they move, it makes it quick and easy to narrow collision checks to those between objects who are in the same or adjacent "buckets".

Ah, so I split up the screen into something like a 8x8 grid, and create lists for each of those cells. Then every object has a variable that tells it what cell it's in, and I add its id to the appropriate list.

Then whenever I want to check collisions, I only have to have the object check its position against every other object in the same list it's in, and the adjacent 8 lists.

Whenever an object moves, I determine if it's list/cell needs to be updated.

In short, it slows down code that deals with movement, but speeds up code that deals with collisions?
 

zetaPRIME

Well-Known Member
Newcomer
Joined
Jan 12, 2015
Messages
87
Trophies
0
Age
32
XP
166
Country
United States
Ah, so I split up the screen into something like a 8x8 grid, and create lists for each of those cells. Then every object has a variable that tells it what cell it's in, and I add its id to the appropriate list.

Then whenever I want to check collisions, I only have to have the object check its position against every other object in the same list it's in, and the adjacent 8 lists.

Whenever an object moves, I determine if it's list/cell needs to be updated.

In short, it slows down code that deals with movement, but speeds up code that deals with collisions?
Well, it's not quite as simple as an 8x8 grid (it's a set of 2x2s split into 2x2s themselves as needed, generally) but that's the general idea. Someone's probably already made a Lua implementation of the concept... and perhaps it's the sort of thing that LPP might benefit from having implemented on the c++ side?
 
D

Deleted User

Guest
The folder structure should be:
Code:
/3ds/Eucliod/Eucliod.3dsx
/3ds/Eucliod/index.lua
/3ds/Eucliod/rsrc/*.*
Although it's no big deal where you put the root Eucliod folder.
The index.lua file will look in the directory of where it exists for /rsrc/, so index.lua, Eucliod.3dsx, and the rsrc folder must all be in the same folder. Screenshots and Levels folders aren't critical but they must be in the same folder as the aforementioned files or the game will freeze when taking a screenshot or loading a level, respectively.

Maybe I should just pack it all in a folder structure extractable to root.

WOT
If you do decide to do this, can you make a separate folder for custom made levels please? :) I really love the game so far! If you find out how to add some music to it- it work strenghen the game to over 9000!..... Percent awesome that is!
 
D

Deleted User

Guest
Sorry that it took so long. How's this?

Looks fun, might get it when more work gets put into it

I was expecting a bullethell as intense as touhou though... i'm sure you can add difficulty settings eventually
 

HexZyle

Pretty Petty Pedant
OP
Member
Joined
Sep 12, 2015
Messages
300
Trophies
0
XP
452
Country
Australia
Looks fun, might get it when more work gets put into it

I was expecting a bullethell as intense as touhou though... i'm sure you can add difficulty settings eventually

I was playing in slowmo since I was using the 3DS itself to record the video, so I was keeping the enemies under control. It gets way more hectic if you don't shoot stuff the instant it spawns (or if you don't shoot at all) and the third wave of the second boss (which I have no screenshots or video of yet) is especially nasty, it's been a total headache to bugtest because it's hard to get to, and hard to complete. (in that video I died right before the second stage boss)
I'll get some more footage later, right now I'm working on the third boss.

I don't think I'll be able to get to the point with a 100+ bullets on screen yet, because the code still needs to be optimized (the 3DS lags when doing too many of my collision calculations)
It's something I intend to improve as I develop more levels.
 
Last edited by HexZyle,

HexZyle

Pretty Petty Pedant
OP
Member
Joined
Sep 12, 2015
Messages
300
Trophies
0
XP
452
Country
Australia
the third wave of the second boss (which I have no screenshots or video of yet) is especially nasty, it's been a total headache to bugtest because it's hard to get to, and hard to complete.

At least I thought it was. I just had a run through it and realised how easy it was and that it's got way too little health:



When I was programming and testing it I must have been super tired.
 
Last edited by HexZyle,
  • Like
Reactions: Deleted User
D

Deleted User

Guest
At least I thought it was. I just had a run through it and realised how easy it was and that it's got way too little health:



When I was programming and testing it I must have been super tired.

looking at that preview made me notice the lack of a boss health bar, i'll assume that gets implemented soon? maybe on the bottom screen
 

HexZyle

Pretty Petty Pedant
OP
Member
Joined
Sep 12, 2015
Messages
300
Trophies
0
XP
452
Country
Australia
looking at that preview made me notice the lack of a boss health bar, i'll assume that gets implemented soon? maybe on the bottom screen
Absolutely. I added that to my to-do list like an hour ago.

Also, the bosses clearing the bullets between each phase is a feature being added into the release I'm working on, and right now it's very choppy and jarring. I've yet to add some animations for it.

EDIT: I just realized how I cleared that boss so fast. In the release I'm working on now, I've fixed the hitboxes so every enemy has a unique hitbox, instead of it being like, 15x15 for everything. Bosses, due to their large graphic, have MASSIVE hitboxes now.

EDIT2: Added Bullet clear animation, looks freaking trippy IMO
 
Last edited by HexZyle,
D

Deleted User

Guest
Absolutely. I added that to my to-do list like an hour ago.

Also, the bosses clearing the bullets between each phase is a feature being added into the release I'm working on, and right now it's very choppy and jarring. I've yet to add some animations for it.

EDIT: I just realized how I cleared that boss so fast. In the release I'm working on now, I've fixed the hitboxes so every enemy has a unique hitbox, instead of it being like, 15x15 for everything. Bosses, due to their large graphic, have MASSIVE hitboxes now.
maybe code it so that the hitbox is only the graphic? like, damage only counts if the bullet touches the texture of the boss
 

Rinnegatamante

Well-Known Member
Member
Joined
Nov 24, 2014
Messages
3,162
Trophies
2
Age
29
Location
Bologna
Website
rinnegatamante.it
XP
4,857
Country
Italy
What's the current collision system check?
At least for player detection, since the only point you have to hit is the little ball at the center you can just do a tricky way to check it:

1) Make bullets getting printed ON TOP of player sprite.
2) Check with a GetPixel on the position of the player ball if the color is bullet color or not (i'm assuming enemy bullet is in a different color, even only a -1 in R is enough to do such trick).
3) If color = bullet -> player got hit -> player dies

IT should be relatively fast and allows you to not iterate for every shooted bullet the same checks.
 

HexZyle

Pretty Petty Pedant
OP
Member
Joined
Sep 12, 2015
Messages
300
Trophies
0
XP
452
Country
Australia
What's the current collision system check?
At least for player detection, since the only point you have to hit is the little ball at the center you can just do a tricky way to check it:

1) Make bullets getting printed ON TOP of player sprite.
2) Check with a GetPixel on the position of the player ball if the color is bullet color or not (i'm assuming enemy bullet is in a different color, even only a -1 in R is enough to do such trick).
3) If color = bullet -> player got hit -> player dies

IT should be relatively fast and allows you to not iterate for every shooted bullet the same checks.

The current hit detection is a simple x and y comparison magic numbers (n) I input based on the shape and size of the sprite:

My collision code is simply:
Code:
if object_x-n < bullet_x and object_x+n > bullet_x and object_y-n < bullet_y and object_y+n > bullet_y then
    --collided
end
for each object the bullet can collide with (for the player's bullets, this is enemies, for the enemy bullets, this is the player)

The change I mentioned earlier only applies to player bullet to enemy hitbox detection, since before now I was just flagging a bullet as collided once it was less than 8 pixels either side of x and y of each enemy, and now what the bullet does is checks up a database based on what enemy it's comparing itself against. The old method made it tricky to land hits on bosses with certain weapons like Photon and Missile, but now bosses just soak up bullets, and you can hit them from more areas, so I'm increasing their health dramatically to compensate. There will be some smaller bosses later on.

Infact I'm working on one I'm calling "Odin", right now. Originally it was going to be an elite mob but I realised he's a complete fucker to kill because of how much he moves, and he'd pester you for the entire level if you didn't get rid of him, so I just made him a boss outright.

That get pixel idea sounds great though for player hit detection, and really and truly solves my issue with non-circular bullets (those diagonal bullets that killed me in the Cicada video actually have a square hitbox, and I was rather uncomfortable leaving them ingame once I figured this could end up killing unaware players) The ship's hitbox is approximately 3x3 (due to some graphical and programming inconsistancies I need to correct), although the core's graphic has a volume of 5 pixels, not 9, so this'd really solve the disconnect between the hitbox graphic and its actual border. Is it okay to do the getpixel check on 5 pixels per step or is that too much?
 
Last edited by HexZyle,

Rinnegatamante

Well-Known Member
Member
Joined
Nov 24, 2014
Messages
3,162
Trophies
2
Age
29
Location
Bologna
Website
rinnegatamante.it
XP
4,857
Country
Italy
So my collision detection theory should be much faster compared to yours since you'll not need to do a single calculation for every enemy bullet but you'll need only a couple of checks based on how much pixels you want to be the player "vital point".

I used that kind of collision detection in this very old project (it was made when lpp-3ds was released for the very first time): https://gbatemp.net/threads/pixelroad-a-stupid-game-hb-to-test-lpp.375292/
 
Last edited by Rinnegatamante,

HexZyle

Pretty Petty Pedant
OP
Member
Joined
Sep 12, 2015
Messages
300
Trophies
0
XP
452
Country
Australia
I was expecting a bullethell as intense as touhou though... i'm sure you can add difficulty settings eventually

I don't think I'll be able to get to the point with a 100+ bullets on screen yet, because the code still needs to be optimized (the 3DS lags when doing too many of my collision calculations)

So my collision detection theory should be much faster compared to yours since you'll not need to do a single calculation for every enemy bullet but you'll need only a couple of checks based on how much pixels you want to be the player "vital point".

WITNESS THE HORROR

gif01.gif


Admittingly the game does drop down to a stable 30fps instead of 60fps when this many bullets are on screen, but it was a neat test of what the game is now capable of. (and it has given me the idea of using frame capping to make this game run flawlessly for the O3DS)

What's especially exciting is the code that handles accessing the bullet's data is still unoptimized, and having 100+ bullets on screen as above gives a great deal of incentive to optimize that, so I should be able to get this to run even smoother!
 
Last edited by HexZyle,
  • Like
Reactions: SLiV3R
D

Deleted User

Guest
WITNESS THE HORROR

gif01.gif


Admittingly the game does drop down to a stable 30fps instead of 60fps when this many bullets are on screen, but it was a neat test of what the game is now capable of. (and it has given me the idea of using frame capping to make this game run flawlessly for the O3DS)

What's especially exciting is the code that handles accessing the bullet's data is still unoptimized, and having 100+ bullets on screen as above gives a great deal of incentive to optimize that, so I should be able to get this to run even smoother!
Holy BUTTS! PLEASE ADD THIS AS AN IMPOSSIBLE MODE! :D
 

HexZyle

Pretty Petty Pedant
OP
Member
Joined
Sep 12, 2015
Messages
300
Trophies
0
XP
452
Country
Australia
What's the current collision system check?
At least for player detection, since the only point you have to hit is the little ball at the center you can just do a tricky way to check it:

1) Make bullets getting printed ON TOP of player sprite.
2) Check with a GetPixel on the position of the player ball if the color is bullet color or not (i'm assuming enemy bullet is in a different color, even only a -1 in R is enough to do such trick).
3) If color = bullet -> player got hit -> player dies

IT should be relatively fast and allows you to not iterate for every shooted bullet the same checks.

So I've been trying for a while to get this to work. I've been using the Screen.getPixel() function because the way Graphics.getPixel() is documented makes it sound like it's only useful for gpu textures, rather than the entire screen.
I've been doing a printout of the number returned by Screen.getPixel() and it's just been giving me 16776961 and 16777012, which is weird since the other colors in my game when I print them out with my rudimentary text print function give 5056257 (the color of bullets), 14920564 (The background color), 11753985 (The ship color) and 1 (white, the ship's core)

I'm using the following graphical functions in this order:
Code:
Screen.waitVblankStart()
Screen.refresh()
Graphics.initBlend(TOP_SCREEN)
--game draws screen features
Graphics_termBlend()
Screen.getPixel(x,y,TOP_SCREEN)
Screen_flip()
 
Last edited by HexZyle,
  • Like
Reactions: Deleted User

Site & Scene News

Popular threads in this forum

General chit-chat
Help Users
  • BigOnYa @ BigOnYa:
    Did you pay your power bill? Or give all yo money to my wife, again.
  • K3Nv2 @ K3Nv2:
    Oh good the estimated time is the same exact time they just said
    +1
  • BigOnYa @ BigOnYa:
    Load up your pc and monitor, and head to a McDonalds dining room, they have free WiFi
  • K3Nv2 @ K3Nv2:
    Sir please watch your porn in the bathroom
    +2
  • BigOnYa @ BigOnYa:
    No sir we can not sell you anymore apple pies, after what you did with the last one.
  • K3Nv2 @ K3Nv2:
    We ran out
  • HiradeGirl @ HiradeGirl:
    for your life
    +1
  • K3Nv2 @ K3Nv2:
    My life has no value my fat ass is staying right here
  • K3Nv2 @ K3Nv2:
    Nearly 4 hours without power :(
  • Veho @ Veho:
    SO POWERLESS
  • K3Nv2 @ K3Nv2:
    Tell Kanye I need power
  • DinohScene @ DinohScene:
    Better start running in your hamster wheel
    +1
  • Psionic Roshambo @ Psionic Roshambo:
    Meth addicts on a treadmill connected to a generator "Unlimited POWER!!!'
  • Veho @ Veho:
    Before or after a hit?
  • Veho @ Veho:
    Do you dangle a baggie in front of them, like a carrot?
  • The Real Jdbye @ The Real Jdbye:
    they're the same thing
  • The Real Jdbye @ The Real Jdbye:
    i like that idea
  • Veho @ Veho:
    What's the same thing?
  • The Real Jdbye @ The Real Jdbye:
    before or after a hit
  • Veho @ Veho:
    Nah, a hit gives them mad meth powers, but makes them more difficult to control.
  • Veho @ Veho:
    Before a hit they're like zombies, persistent but slow.
  • Veho @ Veho:
    It's a tradeoff.
    Veho @ Veho: It's a tradeoff.