After some pondering – I decided I just keep going and see where coding leads me.
Thanks for all suggestions and kind words!
Following optimizations have been done:
– halfed the animation size of (most) bonus
– rotation of enemies are now only 8 directions (instead of 16)
– optimized bank switching
– optimized game loop
– implemented horizontal mirroring of patterns
– reduced enemy “level” information
– reduced a couple of macro based “coding” to subroutines – which cost quite a few cycles
– and probably more stuff I can’t remember
To get a “feeling” of the size and stuff that is missing I copy/pasted from Release the title music and highscore table/ editing / saving.
I plan to implement an “own” Game Over and Highscore screen at one time – but for now its usable and hopefully uses about as many bytes as the things I plan to do.
I decided on a theme for the next levels – which will be more “robotic” – and the new “Big Bug” will look a bit “sinistarish” – “Beware they live!”
I’ll probably reduce the vector count considerably from above image – but that was a first “start”.
Lets get a bit more into the game “mechanics”.
Enemies
Enemies are defined with an EnemyDefinition.
struct EnemyDefinition ds ANGLE8_TABLE,2 ; if zero -> BigBug ds BUG_ENEMY_HP, 0 ds ENEMY_STRENGTH,1 ; HP ds WAIT_ANIM_TABLE,2 ds ENEMY_BULLET_SPEED, 1 ; bug only (for now), lower nibble speed, uppernibble #xnnn, x= 1 can fire missiles ds ADDITIONAL_TYPE_INFO,1 end struct
As of now two different enemies exist
a) “normal” enemies
b) Big bugs
Normal enemies
– enter the game in patterns
– behavior of pattern and intro can be modified with “ADDITIONAL_TYPE”
– normal behavior:
- – intro via a pattern
– after pattern a “delay” is done (enemy invisible)
– enemy enters screen at a random position at the top of the screen
– enemy goes to its waiting position
– waiting position:
- – 20 different positions, where enemies wait and “wobble”
– waiting positions can be defined per level (pointer to waiting position table)
– from waiting positions attack patterns are randomly initiated
(count of attack pattern using enemies at the same time can be set via level information)
– enemies can shoot (count of maximum shots per level can be set per level)
– probability of shooting (and of bonus drop) can be set per level
The normal behaviour of an enemie can be modified by “ADDITIONAL TYPE” definitions, as of now:
- TYPE_NONE = 0
- TYPE_DIRECT_WAIT = %00000001
– does not enter a “delay”, will not be invisible, from last “intro pattern” position, the enemy moves to waiting position - TYPE_DONT_SHOOT = %00000010
– this enemy can not shoot – never! - TYPE_DONT_ATTACK = %00000100
– this enemy will not initiate an attack pattern
(all three combined can be used to define “blockers”) - TYPE_DONT_WAIT = %00001000
– this enemy behaves in a “normal” level like a “kamikaze” attacker
(it does not enter a waiting position after intro pattern – it “vanishes” instead)
this can be used to have larger intro waves – but still restrict the overall enemy count to 20 on screen!
Blocker example:
The above shown blockers “protect” the attacking enemies. Each blocker in the example has about 20 hitpoints.
Attack Pattern
Addition to attack patterns (more info on attack patterns: Vectorblade II) – attack pattern are really something one would nowadays call “scripted enemy behaviour”. Anyway attack sub-pattern definition can now also include “loops” – so the order of sub-patterns (in one attack pattern) is not necessarily linear anymore.
Thats all for today.
Malban
Great to see you are carrying on with this project. We are all behind you on this.
Arthur.
Impressive, Most Impressive!
This is ACE!
Die Gegner sehen echt super aus!
“Beware I live!” LOL!!!
Anyone who puts Sinistar in a game has instantly won my heart.
what advantages are there to structs btw? just abstraction/organization? any speed or code size benefits?
I was just looking at VRelease and I think you have a bunch of structs in objects.i that are never used (or I am more blind than I thought)
Structs in ASM a basically a “clean” way to define constant offsets for indexed data.
You can use them losely and “forget” them – they don’t take up any space unless you actually allocate them.
For me it is much more easy to follow my code to read
– ldd MONSTER_HP,x
Than
– do a ldd 2,x
Also if I ever “change” the struct – the code is “updated” immediately and I don’t have to search and replace everything.
By now I use structs as often as I can and I never really saw any disadvantage.
You just have to look out not to define the same name twice (with different offsets).
Also in case of Release (and Vectorblade) – you can use different struct definitions “easily” on the same memory locations.
In case of Release all enemies are kept in an “Object” struct. But once I know what kind of enemy I am dealing with I use the specific enemy struct to address the object data.
So the same memory location has different “meanings” in different enemy contexts.
See also: Structure Gambling
ok I’ll look at it. I might reserve this knowledge for the future, as my current game isn’t so bad already. (although i had one idea to speed up some table look ups)