# Arcade shooters on the z80 machines. Logic

From a programmer's perspective. You have an 8bit machine, only small amount of ram. And you have to design bullets, sprites, collision detection, character that moves, effects. So much stuff from parallax scrolling, line interrupts etc.
how would your main loop look like? I know of the konami route on msx. That is the vdp syncro interrupt on address f9da and fd9f.

I also read a book of the maker of rtype for the zx spectrum. It had many details rewarding designing an arcade shooter.

Would love to hear your stories.

Now back in the 80 we used to have so good compact game logic behind.
Now a hello world program on ps4 needs half a giga of hd space. (OK OK THIS IS A JOKE)

Cant seem to be able to edit my post under chrome android to correct mistakes . Was the edit feature removed?
Edit:found in phone for some reason the buttons are not present until you click on post.

Actually, I think that the Konami way of doing things is quite intelligent ... But personally, I use a timer that is incremented on the ISR (from 0 to 60 for example, and then it starts again). Then, my main loop is :

- Is there player input ?
- Yes : move the player around, then go back to loop
- No : check ISR timer
- If ISR timer = 0 then scroll screen
- if ISR timer is a multiple of 5 then move enemies
- if ISR timer is a multiple of 10 then move something else
- ...
- Go back to loop

You get the idea

I was curious about the order of sprite collision detection, scrolling and shooting missiles. How many t states are used? How bad or good is the vdp load?

Hi Nikodr, this is the exact game loop used in Transball (not a shooter, but you can get the idea):

```Game_Loop_loop:
;; check if ship collided:
ld a,(shipstate)
and a   ;; equivalent to cp 0, but faster
jp nz,Ship_collided

;; check if level is complete
ld a,(levelComplete)
and a   ;; equivalent to cp 0, but faster
jp nz,Level_complete

call checkInput
call applyGravityAndSpeed
call ballPhysics
call enemyUpdateCycle
call tankUpdateCycle
call checkForShipToMapCollision
call calculate_map_offset
call calculate_ship_sprite_position
call calculate_ball_sprite_position
call calculate_bullet_sprite_positions
call calculate_enemy_bullet_sprite_positions
call checkForShipToEnemyBulletCollision     ;; this needs to go after 'calculate_enemy_bullet_sprite_positions'
;; since collisions are done in screen coordinates, to make sure it's done based
;; on what the player sees
call updateTimeAndFuel
call mapAnimationCycle
call renderExplosions
call changeSprites

call SFX_INT

ld a,(current_game_frame)
ld b,a
Game_Loop_wait_for_next_frame:
ld a,(current_game_frame)
cp b
jp z,Game_Loop_wait_for_next_frame

ld a,(desired_vertical_scroll_for_r23)
ld (vertical_scroll_for_r23),a
ld a,(desired_horizontal_scroll_for_r18)
ld (horizontal_scroll_for_r18),a
ld hl,(desired_map_offset)
ld (map_offset),hl
ld hl,(desired_map_offset+2)
ld (map_offset+2),hl
call drawSprites
call renderMap

jp Game_Loop_loop
```

Full source code here: https://github.com/santiontanon/transballmsx

As for the limits on the number of bullets/etc. I limited it to 4 player bullets, 4 enemy bullets, 2 explosions, 32 enemies, and 64 tile animations at once in the same map. Doing experiments with timing, these seemed like large enough numbers while keeping the framerate constant. I had to redesign some of the levels to fit these constraints toward the end of game development, since I had too many animations and enemies in some levels :)

Even the order in a loop matters in some programming languages. Not only to determine some conditions in the loop, also performance wise.
In my little spare time I am busy in MSX-C with a vertical shooter, just done a total rewrite, which also meant rearranging the main game loop. I also use gamestat, to jump easier into certain conditions.
The order in a game loop varies I have noticed. Like the example of the post above, i have renders mostly at the end.

My MSX profile