Enemy waves spawning
I've been asked how the game is managing enemy spawning and since this is a still in development part of the game, I'll try to explain it here and maybe some new ideas will come out of this.
Some of the choices are also dictated by pico-8 code limitations so are not optimal for every situations but they work for me.
I went through three different revision of this system and I already have some notes on how I want to evolve it a bit further, but so far it's as follows (for most enemies except a coupe of special cases) :
1-enemy data
enemy data is split in 2 tables, one (e_data) with all the common properties for all enemies of the same kind (starting hp, half width, half height, shooting rate, horizontal spacing in a wave, score), another (enemies) one with the data for a single wave (enemy type, x starting position, y starting position, n. of enemies in this wave, bitmask of which enemy will shoot in this wave)
so for example
e_data = { {1,4,4,150,16,10}, -- enemy 1, hp = 1, w/2 = 4, h/2 = 4, shooting rate = 150, one enemy every 16 pixels, score = 100 {1,8,8,110,20,20}, -- enemy 2, hp = 1, w/2 = 8, h/2 = 8, shooting rate = 110, one enemy every 20 pixels, score = 200 ... } enemies = { 1,1289,12,8,0b00101101, -- wave of enemy 1, starts at world x 1289, world y 12, contains 8 enemies, 3rd,5th,6th,8th enemies will shoot 2,1342,80,3,0b100, -- wave of enemy 2, starts at world x 1342, world y 80, contains 3 enemies, 1st enemy will shoot 2,1560,60,4,0b0100, -- wave of enemy 2, starts at world x 1560, world y 60, contains 4 enemies, 2nd enemy will shoot ... }
2-enemy activation
player's progress through a stage is determined in a camera_x variable and every update cycle, the enemies table is traversed and if one of the waves starting x - the half width is < than camera_x+128 the wave gets activated by adding N. of enemies of that type to the enemies list just after the wave definition. each copy of the enemy gets a copy of the e_data fields, plus some additional initialized fields, the most important one is an index in the wave. Each enemy y coord is set to the wave y and each x is Transformed to Screen-Space Coordinates (subtracting camera_x from the wave starting position), so if we are at camera_x 1208 , the second wave in enemies will get activated and its enemies will be placed at 128, 148, 168 (3 copies, with 20 px spacing)
... foreach(enemies[current_stage],enemy_update) ... function enemy_update(e) if enemy_visible(e) then ... end end function enemy_visible(e) local function enemy_activate(en,idx) local camera_x,e_data,unpack,rnd,_ENV =camera_x,e_data,unpack,rnd,en id,x,y,copy,who = unpack(e) hp,w,h,shot,dw,score = unpack(e_data[id]) cnt,r,hit,i=0,0,0,idx local ws = (2^i & who) tshot = ws > 1 and rnd(shot+1)\1 or ws*shot x-=camera_x end if not e.i and e[2]-e_data[e[1]][2]<camera_x+128 then enemy_activate(e,0) for i=1,e.copy-1 do t={} enemy_activate(t,i) add(enemies[current_stage],t) e.x+= e.i*e.dw end end if (e.i and e.x+e.w<-48) del(enemies[current_stage],e) return false return e.i and (e.i>0 or e.x-e.w < 128) end
Once the enemy e has an index field it will receive an enemy_update(e) call and an enemy_draw(e) call so all enemies in the wave will move at proper distance and speed, even if they are still offscreen
If an enemy goes off-screen to the left far enough, it is removed form the table so it's not updated or drawn any longer.
If I disable x-movement you can see the waves spawning off-screen and waiting there, to be scrolled through
3-notes and improvements
the tricky part was to get the activation/positioning correct for the whole wave so enemies offscreen are following the first one which is already visible. Originally enemies were all processed in world coordinates while bullets and player were in screen coordinates but this had a lot of unnecessary code duplication or additional function parameters. The new conversion to screen space is easier.
Right now, when I spawn the enemies, the first enemy's fields are actually added to the wave object, so the first enemy is a special case containing both the original spawn fields and the single enemy fields and this requires some special handling but I plan to change it soon, so there will be 2 separate lists, the wave spawn list and the real enemy update/draw list.
Get R-Type
R-Type
A pico-8 port of the classic 1987 Irem shooter
More posts
- Update 1.4Apr 11, 2022
- Updated to v1.2Nov 12, 2021
- let's compare...Oct 17, 2021
- Update to v1.1Oct 09, 2021
- Pico-8 R-type in 32kbOct 01, 2021
- Gameplay trailerSep 28, 2021
- Stage 3Sep 13, 2021
- Demo now availableJun 04, 2021
Leave a comment
Log in with itch.io to leave a comment.