Sega Master System / Mark III / Game Gear|
SG-1000 / SC-3000 / SF-7000 / OMV
Home - Forums - Games - Scans - Maps - Cheats - Credits
Music - Videos - Development - Hacks - Translations - Homebrew
Swabby (SMS-version) - Development ThreadPosted: Fri Apr 29, 2016 8:30 pm
To keep myself motivated and focused, I have decided to make a development thread for my attempts at enhancing Swabby as I port it from GG to SMS.
I'm rewriting the code from scratch, with emphasis on more structured and encapsulated modules. Swabby (GG) started from a background scrolling routine. Swabby (SMS) starts from attention to sprites/objects (player, enemies, bullets etc.). By now I have made a fairly generic object handler that will allow for more - and more varied - objects on the screen, compared to the compo version. Currently I'm looking into creating interesting enemy patterns, new/more enemies and also upgrades to Swabby. I use Cloud Master for my main reference (for patterns and gameplay 'feel'). And then Deathsmiles for a kind of far-fetched meta-meta-meta spiritual inspiration :) ...
Anyway, as tibone has already remarked in Swabby's compo thread, you cannot have a shmup with a one-bullet-at-a-time limitation on the player. So I'm planning to have about two quick weapon upgrades to give the player more - and more damaging - bullets. And also a speed upgrade. I think it would look cool if Swabby visually changes as he powers up, so I have begun to sketch various ideas for weapons and jet/motor add-ons.
Currently I like the gatling gun the most. And the small pair of jet motors. What do you think?
||Posted: Sat Apr 30, 2016 7:13 am|
I'm actually currently looking into shmup development myself, and I'm facing the same questions: How to handle enemy formations, or collisions with lots of bullets (both from the player and the enemies) and other objects on screen, and so on. So I'm very interested to hear about your progress.
I'm currently considering trying to disassemble a fairly small shmup like Astro Warrior or Satellite 7 to look how those handle the stuff. (The former has some really nice formations, the latter is good with bullets.)
Btw, I love those upgrade graphics.
||Posted: Sat Apr 30, 2016 9:28 am|
a shmup on SMS is a kind of pain in the... you know.
I mean, I'm working on Weka Invaders and I've already hit any kind of limit, and each time I do that I have to figure a way out (and I still have to do that for some stuff...)
First, there's the 8-sprites-max-per-scanline limit. A bit of flicker is fine, objects disappearing completely is not, too much flicker is acceptable only if it happens very VERY rarely (IMHO of course)
Then, there's the CPU. N bullets that can collide with M objects would theoretically require NxM tests, and you're likely doing all these tests each frame, so you'll end up pretty soon using much more CPU power than you've got available. If keeping N (or M) low isn't an option, you've got few choices, but mostly you'll be trying to avoid as many collision tests as possible. For instance Waimanu bullets can collide with blocks, wekas and the UFO on top. According to the bullet Y position I check collisions with UFO -or- with other objects, but that's surely not a great optimization, but you get the point: you can test a subset of your N bullets against a subset of your M objects.
Finally, I simplified the collision test itself turning it into a simple 'is a point inside a box' test (instead of a full AABB test) and also 'cheating' a bit using unsigned bytes (so I just test for <K and not for >0 ...)
Good luck anyway :)
edit: sorry, my english becomes worse and worse with every day :|
||Posted: Sat Apr 30, 2016 6:32 pm|
Thanks for the hints on Astro Warrior and Satellite 7, Kagesan. These games are new to me. Indeed it is nice to have something relatively simple to get inspiration from.
Like you, sverx, I'm very critical of sprite flickering. I think it makes a game look broken, and back in the days I was (secretly) a little ashamed of my SMS's sometimes heavy flickering games (who said Double Dragon), while my C64 friends seemed to have almost no problems in this regard.
By now I have gotten very fond of the Sonic sprite engine that Glitch points to here http://www.smspower.org/forums/14926-SpriteFlicker. This engine will spare your player sprite from flickering, and it is generally nice, I think. It is almost drop-in sprite handling functionality.
I have then built some meta sprite functions on top of the Sonic engine (inspired by na_th_an in the DevkitSMS topic here: http://www.smspower.org/forums/15228-DevkitSMSDevelopYourHomebrewInC?start=150#89001).
And on top of this, I'm developing structures to handle up to 16 objects at a time. An object holds metasprite info and possibly a lot of other stuff like lives, movement, speed, etc.
Each object takes up 64 bytes in an Object Attribute Table (OAT). I like that acronym very much :) As it shows, I have only used the first 19 bytes by now.
; Object Attribute Table definitions.
.equ OAT_ELEMENT_SIZE 64
.equ MAX_OBJECTS 16
.equ OAT_STATUS 0
.equ OAT_Y 1
.equ OAT_X 2
.equ OAT_META_SPRITE_POINTER_LSB 3
.equ OAT_MOVEMENT 5
.equ OAT_VERTICAL_SPEED 6
.equ OAT_HORIZONTAL_SPEED 7
.equ OAT_ANIM_TABLE_BASE_ADDRESS_LSB 8
.equ OAT_ANIM_TABLE_INDEX 10
.equ OAT_ANIM_TIMER 11
.equ OAT_MOVEMENT_PATTERN_POINTER_LSB 12
.equ OAT_PATTERN_TIMER 14
.equ OAT_DELAY_COUNTER 15
.equ OAT_DELAY_VALUE 16
.equ OAT_META_SPRITE_FLAGS 17
.equ OAT_DESTROY_OBJECT 18
; Definitions for object's movement type.
.equ STATIC 0 ; Ignore vertical and horizontal speeds. Stay still.
.equ JOYSTICK_1 1 ; Object is controlled with joystick in port 1.
.equ JOYSTICK_2 2 ; Object is controlled with joystick in port 2.
.equ SIMPLE_MOVEMENT 3 ; Object moves by values in v- and h-speed.
.equ PATTERN 4 ; Object moves according to a pattern.
.ramsection "Objectlib Variables" slot 3
ObjectAttributeTable dsb 16*OAT_ELEMENT_SIZE
; 0 : Status
; 1 : Y
; 2 : X
; 3-4 : MetaSpritePointer
; 5 : Movement
; 6 : Vertical speed
; 7 : Horizontal speed
; 8-9 : AnimTableBaseAddress
; 10 : AnimationTableIndex
; 11 : AnimationTimer
; 12-13 : Movement pattern table pointer.
; 14 : Pattern timer.
; 15 : DelayCounter - counts from DelayValue to zero.
; 16 : DelayValue - how many frames to skip during each movement.
; 17 : MetaSpriteFlags - uuuu uulr
; - enable left or right mask (for horizontal clipping).
; 18 : Destroy object
; 19-63 : Unused
||Posted: Sun May 01, 2016 4:14 am|
This is just a theory, but lets say:
Your basic problem is that you have N bullets that move at >1 pixel per frame OR that the bullets are so numerous that you can't check all of their collisions each frame.
So instead you check as many bullets as you can.
The remaining bullets have their hitboxes elongated by their movement.
If you have a bullet * with hitbox # you elongate the hitbox with # each vbl.
In the hitbox handler, you reset the hitbox to *.
In other words, if you check the first third of the screen (assuming bullets are sorted), the middle and last section has its bullet hitboxes elongated to ##. Then the middle section is checked while the bottom section has its hitboxes elongated to ###.
It still requires processing, but less than when checking each hitbox each vbl.
||Posted: Sun May 01, 2016 5:38 am|
I plan to keep the numbers relatively low. No danmaku for me.
I will test each of Swabby's bullets (<7) against each enemy on screen (<7). Then I will test each enemy bullet (<5) against Swabby. I plan to program the waves so that I can get by with max 16 objects (player, enemies, bulllets) on screen.
||Posted: Sun May 01, 2016 6:57 am|
|I don't think I had any issues with CPU in "ono", but instead I had a system where I wouldn't spawn enemies if it would exceed the sprite limit. It's a bit dialled back from bullet hell, but it seemed hectic enough for me.|
||Posted: Sun May 01, 2016 7:37 am|
Satellite 7 is actually a bit idiosyncratic, but Astro Warrior pretty much has all the shmup basics down: Enemy formations (some pattern-based, some reacting to the player), powerups (including piercing laser), destructible scenery, Gradius-like options, and huge bosses made with background scroll trickery. It's a very solid and much overlooked little game.
Regarding collisions, I think as long as you're not going danmaku you should be fine. This thread has some interesting discussion on how to reduce the work load of the CPU.
I think your approach looks promising, and limiting the number of on-screen enemies to 16 seems reasonable. Even a very busy game like Blade Buster never has more than. (It does have additional bonus items and quite a lot of bullets, but that's another story.)
||Posted: Sun May 01, 2016 11:23 am|
so it's 6*6+4=40 collision tests worst case? It shouldn't be a problem, but it also depends on how much CPU power you can allocate to collision checking, because you've got other things to do beside that.
In Weka Invaders I try not to use more than 40% CPU for collisions in the worst case, because it's already doing a bunch of things even when there are no collisions to check :|
Luckily, Emulicious features a handy profiler... :)
||Posted: Mon May 02, 2016 7:14 am|
|Thanks for all the feedback! I really appreciate it. Yes, it will be around 40 coll. tests at max. Right now real work requires my attention, but I'll soon sit down and make some upgrades, new enemies and waves and get back when I have something to show :)|
||Posted: Mon May 02, 2016 9:09 am|
I think that i already discussed about collisions some time ago here, but i havn't been able to find the thread. I'll explain the method that we have used for Antarex ( https://www.youtube.com/watch?v=1Qr2S8RZXWY)
In any game with horizontal gameplay, you can manage collision on a very efficent way. Let's define two kinds of objects GOOD and BAD. The player and his bullets are GOOD, and the enemies and their bullets are BAD.
You have an array with as many positions as 8px columns are on the screen(32 on SMS) On each frame, you first find in wich column there are GOOD objects and put a reference to that object in this position of the array.
Ex: My ship is 16px long and is on the x = 30, so the ship is on the fourth and the fifth column. Aditionally, the ship has fired its weapon one time, and the bullet i(8px long) is on x = 200, so it's on the 25th column,
So now we have the 4th, 5th and 25th column with references to the player and the player's bullet. Now, we start to search the positions for the BAD objects. If there's an enemy, 16px long , on x = 100, it will spread through the 12th and the 13th column, which are empty, so no need to check collision. If there's a enemy bullet(8px) on x = 25, it will be on the fourth column, so we'll have to check collision with the player.
One of the backdraws of this method is that you have to assure that only one GOOD object is on every 8px column.
In the worst cases, we're checking no more than 12 collisions with the screen full of enemies and bullets
||Posted: Mon May 02, 2016 12:22 pm|
You can have a linked list for each 'slice'. Of course you've got to have very few objects in each slice or you'll just end up with too much overhead and too little gain.
Also, if your ship size is 16 pixel, you'll have it into either 2 or 3 8-pixel slices, according to X position.
||Posted: Mon May 02, 2016 12:31 pm|
Actually, we have implemented a two element list on each position, it's enough for most situations.
And yes, it depends on size and position, each "Object" can span multiple columns.
||Posted: Wed May 04, 2016 9:35 pm|
|Any chance of boss battles? :)|
||Posted: Thu May 05, 2016 6:12 am|
Yeah, high chance of boss battles! I plan to loosely follow the Cloud Master style: A mid-boss made of sprites (around 24x24 pixels) and a super large end-boss made of background tiles. I'm thinking about 8-bit versions of Deathsmiles-inspired bosses like Deathscythe and Tyrannosatan (!!) for the graveyard level, but I'm open to suggestions.
||Posted: Thu May 05, 2016 10:01 am|
Sounds cool! :D
||Posted: Thu May 05, 2016 4:24 pm|
Thanks! yeah, it also looks cool when I close my eyes :) I hope it will turn out OK when I put the pen to the tablet. Bosses will be priority once I get some variations going with regards to enemies and their patterns.
||Posted: Thu May 05, 2016 11:33 pm|
||Posted: Tue May 10, 2016 12:15 pm|
|If you want to keep the Altered Beast theme, i always thought the face-throwing first boss from that game is very shmup-ish. And it would be a good fit for the game. :)|
||Posted: Tue May 10, 2016 7:57 pm|
That is a great idea! He does indeed throw/shoot some mean 'bullets' :) I will seriously consider him for the final boss of level 1, and then a downscaled, Deathsmiles-inspired mid-boss. Having drafted a rotating skull and a caped, spooky fellow, I'm moving towards a 'generic graveyard' theme with regards to sprites at the moment. But I'm planning to not deviate too far from the Altered Beast theme - it is part of the complex, multi-layered narrative under Swabby, after all :) Two-headed wolves, big yellow demons with horns and beheaded skeletons - I'm looking at you guys...
All these new enemies challenge my existing data structures, so I'm reorganizing the code at the moment, when not drawing enemies, bullets and power-up tokens.
||Posted: Sat Jun 11, 2016 9:19 pm|
I decided to create some mockups to direct my coding efforts. In my quest for clean code that works, I'm learning quite a bit, but I'm also facing psidum's point about accepting some degree of messiness to keep my sanity. After having spent some days thinking about a simple yet generalizable way to make my object handler control loading to/indexing tile bank 2 (here I keep my sprite tiles), connected to a general way to store meta sprite data, ram tables for pointers to various assets, etc., etc, etc., I have come to the (rather obvious) conclusion that I should not strive to make a general engine, but rather a somehow specific (but not too specific) engine capable of running the Swabby game.
Anyway, I think it might do me good to take a break from this conversion and come back after some experiments.